diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/Makefile.in | 15 | ||||
-rw-r--r-- | source4/libcli/auth/credentials.c | 213 | ||||
-rw-r--r-- | source4/libcli/util/credentials.c | 21 | ||||
-rw-r--r-- | source4/librpc/idl/netlogon.idl | 14 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.c | 43 |
5 files changed, 262 insertions, 44 deletions
diff --git a/source4/Makefile.in b/source4/Makefile.in index 399027dc16..f156262b97 100644 --- a/source4/Makefile.in +++ b/source4/Makefile.in @@ -179,12 +179,10 @@ SECRETS_OBJ = passdb/secrets.o LIBNMB_OBJ = libcli/unexpected.o libcli/namecache.o libcli/nmblib.o \ libcli/namequery.o -LIBNTLMSSP_OBJ = libcli/auth/ntlmssp.o libcli/auth/ntlmssp_parse.o libcli/auth/ntlmssp_sign.o - LIBSAMBA_OBJ = libcli/util/nterr.o libcli/util/smbdes.o libcli/util/smbencrypt.o LIBCLIUTIL_OBJ = libcli/util/asn1.o \ - libcli/util/smberr.o libcli/util/credentials.o \ + libcli/util/smberr.o \ libcli/util/doserr.o libcli/util/errormap.o \ libcli/util/pwd_cache.o libcli/util/clierror.o libcli/util/cliutil.o @@ -208,6 +206,11 @@ LIBRAW_RPC_OBJ = librpc/rpc/dcerpc.o librpc/rpc/dcerpc_auth.o \ librpc/rpc/dcerpc_util.o \ librpc/rpc/dcerpc_smb.o librpc/rpc/dcerpc_tcp.o +LIBNTLMSSP_OBJ = libcli/auth/ntlmssp.o libcli/auth/ntlmssp_parse.o \ + libcli/auth/ntlmssp_sign.o + +LIBCLIAUTH_OBJ = $(LIBNTLMSSP_OBJ) libcli/auth/credentials.o + LIBRAW_OBJ = libcli/raw/rawfile.o libcli/raw/smb_signing.o \ libcli/raw/clisocket.o libcli/raw/clitransport.o \ libcli/raw/clisession.o libcli/raw/clitree.o \ @@ -219,7 +222,7 @@ LIBRAW_OBJ = libcli/raw/rawfile.o libcli/raw/smb_signing.o \ libcli/raw/rawfileinfo.o libcli/raw/rawnotify.o \ libcli/raw/rawioctl.o libcli/raw/rawacl.o \ $(LIBRAW_NDR_OBJ) $(LIBRAW_RPC_OBJ) $(LIBSAMBA_OBJ) $(LIBCLIUTIL_OBJ) \ - $(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBNMB_OBJ) $(KRBCLIENT_OBJ) + $(RPC_PARSE_OBJ1) $(LIBNMB_OBJ) $(KRBCLIENT_OBJ) $(LIBCLIAUTH_OBJ) LIBSMB_OBJ = libcli/clireadwrite.o libcli/cliconnect.o \ libcli/clifile.o libcli/clilist.o libcli/clitrans2.o \ @@ -448,7 +451,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/torture_util.o torture/nbio.o tortur torture/aliases.o libcli/raw/clirewrite.o $(SMBTORTURE_RAW_OBJ) \ $(SMBTORTURE_RPC_OBJ) -SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) \ +SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBDFS_OBJ) $(PARAM_OBJ) $(LIB_OBJ) NDRDUMP_OBJ = utils/ndrdump.o utils/rewrite.o \ @@ -509,7 +512,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(LIBSMB_OBJ) $(PARAM_OBJ) \ PROTO_OBJ = $(SMBD_OBJ_SRV) \ $(SMBD_OBJ_MAIN) $(PROCESS_MODEL_OBJ) \ $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIBSMB_OBJ) \ - $(LIBRAW_OBJ) $(LIBDFS_OBJ) $(LIBCLIUTIL) $(LIBNTLMSSP_OBJ) \ + $(LIBRAW_OBJ) $(LIBDFS_OBJ) $(LIBCLIUTIL) $(LIBCLIAUTH_OBJ) \ $(SMBW_OBJ1) $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \ $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) \ $(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) $(KRBCLIENT_OBJ) \ diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c new file mode 100644 index 0000000000..6df163bdfc --- /dev/null +++ b/source4/libcli/auth/credentials.c @@ -0,0 +1,213 @@ +/* + Unix SMB/CIFS implementation. + + code to manipulate domain credentials + + Copyright (C) Andrew Tridgell 1997-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/**************************************************************************** +represent a credential as a string +****************************************************************************/ +char *credstr(const uchar *cred) +{ + static fstring buf; + slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X", + cred[0], cred[1], cred[2], cred[3], + cred[4], cred[5], cred[6], cred[7]); + return buf; +} + + +/**************************************************************************** + setup the session key. +Input: 8 byte challenge block + 8 byte server challenge block + 16 byte md4 encrypted password +Output: + 8 byte session key +****************************************************************************/ +void cred_session_key(const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const uint8 md4_pass[16], + uint8 session_key[8]) +{ + uint32 sum[2]; + uint8 sum2[8]; + + sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0); + sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4); + + SIVAL(sum2,0,sum[0]); + SIVAL(sum2,4,sum[1]); + + cred_hash1(session_key, sum2, md4_pass); +} + + +/**************************************************************************** +create a credential + +Input: + 8 byte sesssion key + 8 byte stored credential + 4 byte timestamp + +Output: + 8 byte credential +****************************************************************************/ +void cred_create(uchar session_key[8], struct netr_Credential *stor_cred, time_t timestamp, + struct netr_Credential *cred) +{ + struct netr_Credential time_cred; + + SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp); + SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4)); + + cred_hash2(cred->data, time_cred.data, session_key); + + /* debug output*/ + DEBUG(4,("cred_create\n")); + + DEBUG(5,(" sess_key : %s\n", credstr(session_key))); + DEBUG(5,(" stor_cred: %s\n", credstr(stor_cred->data))); + DEBUG(5,(" timestamp: %x\n", (unsigned)timestamp)); + DEBUG(5,(" timecred : %s\n", credstr(time_cred.data))); + DEBUG(5,(" calc_cred: %s\n", credstr(cred->data))); +} + + +/**************************************************************************** + check a supplied credential + +Input: + 8 byte received credential + 8 byte sesssion key + 8 byte stored credential + 4 byte timestamp + +Output: + returns 1 if computed credential matches received credential + returns 0 otherwise +****************************************************************************/ +int cred_assert(struct netr_Credential *cred, uchar session_key[8], + struct netr_Credential *stored_cred, + time_t timestamp) +{ + struct netr_Credential cred2; + + cred_create(session_key, stored_cred, timestamp, &cred2); + + /* debug output*/ + DEBUG(4,("cred_assert\n")); + + DEBUG(5,(" challenge : %s\n", credstr(cred->data))); + DEBUG(5,(" calculated: %s\n", credstr(cred2.data))); + + if (memcmp(cred->data, cred2.data, 8) == 0) + { + DEBUG(5, ("credentials check ok\n")); + return True; + } + else + { + DEBUG(5, ("credentials check wrong\n")); + return False; + } +} + + +/**************************************************************************** + checks credentials; generates next step in the credential chain +****************************************************************************/ +BOOL clnt_deal_with_creds(uchar sess_key[8], + struct netr_Authenticator *sto_clnt_cred, + struct netr_Authenticator *rcv_srv_cred) +{ + time_t new_clnt_time; + uint32 new_cred; + + DEBUG(5,("clnt_deal_with_creds: %d\n", __LINE__)); + + /* increment client time by one second !?! */ + new_clnt_time = sto_clnt_cred->timestamp + 1; + + /* check that the received server credentials are valid */ + if (!cred_assert(&rcv_srv_cred->cred, sess_key, + &sto_clnt_cred->cred, new_clnt_time)) { + return False; + } + + /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ + new_cred = IVAL(sto_clnt_cred->cred.data, 0); + new_cred += new_clnt_time; + + /* store new seed in client credentials */ + SIVAL(sto_clnt_cred->cred.data, 0, new_cred); + + DEBUG(5,(" new clnt cred: %s\n", credstr(sto_clnt_cred->cred.data))); + return True; +} + + +/**************************************************************************** + checks credentials; generates next step in the credential chain +****************************************************************************/ +BOOL deal_with_creds(uchar sess_key[8], + struct netr_Authenticator *sto_clnt_cred, + struct netr_Authenticator *rcv_clnt_cred, + struct netr_Authenticator *rtn_srv_cred) +{ + time_t new_clnt_time; + uint32 new_cred; + + DEBUG(5,("deal_with_creds: %d\n", __LINE__)); + + /* check that the received client credentials are valid */ + if (!cred_assert(&rcv_clnt_cred->cred, sess_key, + &sto_clnt_cred->cred, rcv_clnt_cred->timestamp)) + { + return False; + } + + /* increment client time by one second */ + new_clnt_time = rcv_clnt_cred->timestamp + 1; + + /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ + new_cred = IVAL(sto_clnt_cred->cred.data, 0); + new_cred += new_clnt_time; + + DEBUG(5,("deal_with_creds: new_cred[0]=%x\n", new_cred)); + + /* doesn't matter that server time is 0 */ + rtn_srv_cred->timestamp = 0; + + DEBUG(5,("deal_with_creds: new_clnt_time=%x\n", (unsigned)new_clnt_time)); + + /* create return credentials for inclusion in the reply */ + cred_create(sess_key, &sto_clnt_cred->cred, new_clnt_time, + &rtn_srv_cred->cred); + + DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->cred.data))); + + /* store new seed in client credentials */ + SIVAL(sto_clnt_cred->cred.data, 0, new_cred); + + return True; +} diff --git a/source4/libcli/util/credentials.c b/source4/libcli/util/credentials.c deleted file mode 100644 index 2c8f7e7423..0000000000 --- a/source4/libcli/util/credentials.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - Unix SMB/CIFS implementation. - code to manipulate domain credentials - Copyright (C) Andrew Tridgell 1997-1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index e0f38ac112..7bdb4ae6ed 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -92,13 +92,13 @@ interface netlogon NT_OWF_PASSWORD ntpassword; } INTERACTIVE_INFO; - typedef struct { - uint8 chl[8]; - } netr_Challenge; + typedef [flag(NDR_PAHEX)] struct { + uint8 data[8]; + } netr_Credential; typedef struct { LOGON_IDENTITY_INFO logon_info; - netr_Challenge chal; + netr_Credential challenge; unistr ntchallengeresponse; unistr lmchallengeresponse; } NETWORK_INFO; @@ -115,13 +115,9 @@ interface netlogon [case(3)] SERVICE_INFO *sinfo; } netr_LogonLevel; - typedef [flag(NDR_PAHEX)] struct { - uint8 cred[8]; - } netr_Credential; - typedef struct { netr_Credential cred; - uint32 timestamp; + time_t timestamp; } netr_Authenticator; typedef struct { diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 0f22b1a44b..68937a4947 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -65,22 +65,26 @@ static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) } -static BOOL test_Challenge(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +static BOOL test_Authenticate(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct netr_ServerReqChallenge r; - struct netr_Credential creds; + struct netr_ServerAuthenticate a; + struct netr_Credential client_chal, server_chal, cred2; + uint8 session_key[8]; + const char *plain_pass; + uint8 mach_pwd[16]; printf("Testing ServerReqChallenge"); - ZERO_STRUCT(creds); + ZERO_STRUCT(client_chal); - generate_random_buffer(creds.cred, sizeof(creds.cred), False); + generate_random_buffer(client_chal.data, sizeof(client_chal.data), False); r.in.server_name = NULL; r.in.computer_name = lp_netbios_name(); - r.in.credential = &creds; - r.out.credential = &creds; + r.in.credential = &client_chal; + r.out.credential = &server_chal; status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -88,8 +92,31 @@ static BOOL test_Challenge(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return False; } + plain_pass = secrets_fetch_machine_password(); + if (!plain_pass) { + printf("Unable to fetch machine password!\n"); + return False; + } + + E_md4hash(plain_pass, mach_pwd); + cred_session_key(&client_chal, &server_chal, mach_pwd, session_key); + + cred_create(session_key, &client_chal, 0, &cred2); + + a.in.server_name = NULL; + a.in.username = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name()); + a.in.secure_challenge_type = 2; + a.in.computer_name = lp_netbios_name(); + a.in.client_challenge = &cred2; + a.out.client_challenge = &cred2; + + status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a); + if (!NT_STATUS_IS_OK(status)) { + printf("ServerAuthenticate - %s\n", nt_errstr(status)); + return False; + } + return True; - } @@ -120,7 +147,7 @@ BOOL torture_rpc_netlogon(int dummy) ret = False; } - if (!test_Challenge(p, mem_ctx)) { + if (!test_Authenticate(p, mem_ctx)) { ret = False; } |