summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/Makefile.in15
-rw-r--r--source4/libcli/auth/credentials.c213
-rw-r--r--source4/libcli/util/credentials.c21
-rw-r--r--source4/librpc/idl/netlogon.idl14
-rw-r--r--source4/torture/rpc/netlogon.c43
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;
}