2 Unix SMB/CIFS implementation.
4 code to manipulate domain credentials
6 Copyright (C) Andrew Tridgell 1997-2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /****************************************************************************
26 represent a credential as a string
27 ****************************************************************************/
28 char *credstr(const uchar *cred)
31 slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X",
32 cred[0], cred[1], cred[2], cred[3],
33 cred[4], cred[5], cred[6], cred[7]);
38 /****************************************************************************
39 setup the session key.
40 Input: 8 byte challenge block
41 8 byte server challenge block
42 16 byte md4 encrypted password
45 ****************************************************************************/
46 void cred_session_key(const struct netr_Credential *client_challenge,
47 const struct netr_Credential *server_challenge,
48 const uint8 md4_pass[16],
54 sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
55 sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
60 cred_hash1(session_key, sum2, md4_pass);
64 /****************************************************************************
69 8 byte stored credential
74 ****************************************************************************/
75 void cred_create(uchar session_key[8], struct netr_Credential *stor_cred, time_t timestamp,
76 struct netr_Credential *cred)
78 struct netr_Credential time_cred;
80 SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp);
81 SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4));
83 cred_hash2(cred->data, time_cred.data, session_key);
86 DEBUG(4,("cred_create\n"));
88 DEBUG(5,(" sess_key : %s\n", credstr(session_key)));
89 DEBUG(5,(" stor_cred: %s\n", credstr(stor_cred->data)));
90 DEBUG(5,(" timestamp: %x\n", (unsigned)timestamp));
91 DEBUG(5,(" timecred : %s\n", credstr(time_cred.data)));
92 DEBUG(5,(" calc_cred: %s\n", credstr(cred->data)));
96 /****************************************************************************
97 check a supplied credential
100 8 byte received credential
102 8 byte stored credential
106 returns 1 if computed credential matches received credential
108 ****************************************************************************/
109 int cred_assert(struct netr_Credential *cred, uchar session_key[8],
110 struct netr_Credential *stored_cred,
113 struct netr_Credential cred2;
115 cred_create(session_key, stored_cred, timestamp, &cred2);
118 DEBUG(4,("cred_assert\n"));
120 DEBUG(5,(" challenge : %s\n", credstr(cred->data)));
121 DEBUG(5,(" calculated: %s\n", credstr(cred2.data)));
123 if (memcmp(cred->data, cred2.data, 8) == 0)
125 DEBUG(5, ("credentials check ok\n"));
130 DEBUG(5, ("credentials check wrong\n"));
136 /****************************************************************************
137 checks credentials; generates next step in the credential chain
138 ****************************************************************************/
139 BOOL clnt_deal_with_creds(uchar sess_key[8],
140 struct netr_Authenticator *sto_clnt_cred,
141 struct netr_Authenticator *rcv_srv_cred)
143 time_t new_clnt_time;
146 DEBUG(5,("clnt_deal_with_creds: %d\n", __LINE__));
148 /* increment client time by one second !?! */
149 new_clnt_time = sto_clnt_cred->timestamp + 1;
151 /* check that the received server credentials are valid */
152 if (!cred_assert(&rcv_srv_cred->cred, sess_key,
153 &sto_clnt_cred->cred, new_clnt_time)) {
157 /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
158 new_cred = IVAL(sto_clnt_cred->cred.data, 0);
159 new_cred += new_clnt_time;
161 /* store new seed in client credentials */
162 SIVAL(sto_clnt_cred->cred.data, 0, new_cred);
164 DEBUG(5,(" new clnt cred: %s\n", credstr(sto_clnt_cred->cred.data)));
169 /****************************************************************************
170 checks credentials; generates next step in the credential chain
171 ****************************************************************************/
172 BOOL deal_with_creds(uchar sess_key[8],
173 struct netr_Authenticator *sto_clnt_cred,
174 struct netr_Authenticator *rcv_clnt_cred,
175 struct netr_Authenticator *rtn_srv_cred)
177 time_t new_clnt_time;
180 DEBUG(5,("deal_with_creds: %d\n", __LINE__));
182 /* check that the received client credentials are valid */
183 if (!cred_assert(&rcv_clnt_cred->cred, sess_key,
184 &sto_clnt_cred->cred, rcv_clnt_cred->timestamp))
189 /* increment client time by one second */
190 new_clnt_time = rcv_clnt_cred->timestamp + 1;
192 /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
193 new_cred = IVAL(sto_clnt_cred->cred.data, 0);
194 new_cred += new_clnt_time;
196 DEBUG(5,("deal_with_creds: new_cred[0]=%x\n", new_cred));
198 /* doesn't matter that server time is 0 */
199 rtn_srv_cred->timestamp = 0;
201 DEBUG(5,("deal_with_creds: new_clnt_time=%x\n", (unsigned)new_clnt_time));
203 /* create return credentials for inclusion in the reply */
204 cred_create(sess_key, &sto_clnt_cred->cred, new_clnt_time,
205 &rtn_srv_cred->cred);
207 DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->cred.data)));
209 /* store new seed in client credentials */
210 SIVAL(sto_clnt_cred->cred.data, 0, new_cred);