From 39a572e0106696e24540d9829812917635c1fd06 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Feb 2006 04:22:32 +0000 Subject: r13539: Add 128 bit creds processing client and server. Thanks to Andrew Bartlett's Samba4 code. Jeremy. (This used to be commit a2fb436fc5dd536cfe860be93f55f9cb58139a0e) --- source3/lib/hmacmd5.c | 25 +++++------ source3/libsmb/credentials.c | 88 ++++++++++++++++++++++++++++++++++---- source3/rpc_client/cli_netlogon.c | 3 +- source3/rpc_server/srv_netlog_nt.c | 6 ++- 4 files changed, 98 insertions(+), 24 deletions(-) diff --git a/source3/lib/hmacmd5.c b/source3/lib/hmacmd5.c index f436fd30c0..c94702bb08 100644 --- a/source3/lib/hmacmd5.c +++ b/source3/lib/hmacmd5.c @@ -28,14 +28,14 @@ /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. ***********************************************************************/ -void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) + +void hmac_md5_init_rfc2104(const unsigned char *key, int key_len, HMACMD5Context *ctx) { int i; /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) - { - uchar tk[16]; + if (key_len > 64) { + unsigned char tk[16]; struct MD5Context tctx; MD5Init(&tctx); @@ -53,8 +53,7 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) memcpy( ctx->k_opad, key, key_len); /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) - { + for (i=0; i<64; i++) { ctx->k_ipad[i] ^= 0x36; ctx->k_opad[i] ^= 0x5c; } @@ -66,14 +65,14 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) /*********************************************************************** the microsoft version of hmac_md5 initialisation. ***********************************************************************/ -void hmac_md5_init_limK_to_64(const uchar* key, int key_len, + +void hmac_md5_init_limK_to_64(const unsigned char* key, int key_len, HMACMD5Context *ctx) { int i; /* if key is longer than 64 bytes truncate it */ - if (key_len > 64) - { + if (key_len > 64) { key_len = 64; } @@ -96,7 +95,8 @@ void hmac_md5_init_limK_to_64(const uchar* key, int key_len, /*********************************************************************** update hmac_md5 "inner" buffer ***********************************************************************/ -void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) + +void hmac_md5_update(const unsigned char *text, int text_len, HMACMD5Context *ctx) { MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ } @@ -104,7 +104,7 @@ void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) /*********************************************************************** finish off hmac_md5 "inner" buffer and generate outer one. ***********************************************************************/ -void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) +void hmac_md5_final(unsigned char *digest, HMACMD5Context *ctx) { struct MD5Context ctx_o; @@ -121,7 +121,8 @@ void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ -void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest) + +void hmac_md5( unsigned char key[16], unsigned char *data, int data_len, unsigned char *digest) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(key, 16, &ctx); diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 5026f513ab..975f9bca49 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -25,7 +25,7 @@ Represent a credential as a string. ****************************************************************************/ -char *credstr(const uchar *cred) +char *credstr(const unsigned char *cred) { static fstring buf; slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X", @@ -34,6 +34,58 @@ char *credstr(const uchar *cred) return buf; } +/**************************************************************************** + Setup the session key and the client and server creds in dc. + ADS-style 128 bit session keys. + Used by both client and server creds setup. +****************************************************************************/ + +static void creds_init_128(struct dcinfo *dc, + const DOM_CHAL *clnt_chal_in, + const DOM_CHAL *srv_chal_in, + const char mach_pw[16]) +{ + unsigned char zero[4], tmp[16]; + HMACMD5Context ctx; + struct MD5Context md5; + + /* Just in case this isn't already there */ + memcpy(dc->mach_pw, mach_pw, 16); + + ZERO_STRUCT(dc->sess_key); + + memset(zero, 0, sizeof(zero)); + + hmac_md5_init_rfc2104(mach_pw, 16, &ctx); + MD5Init(&md5); + MD5Update(&md5, zero, sizeof(zero)); + MD5Update(&md5, clnt_chal_in->data, 8); + MD5Update(&md5, srv_chal_in->data, 8); + MD5Final(tmp, &md5); + hmac_md5_update(tmp, sizeof(tmp), &ctx); + hmac_md5_final(dc->sess_key, &ctx); + + /* debug output */ + DEBUG(5,("creds_init_128\n")); + DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data))); + DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data))); + dump_data_pw("\tsession_key ", (const unsigned char *)dc->sess_key, 16); + + /* Generate the next client and server creds. */ + + des_crypt112(dc->clnt_chal.data, /* output */ + clnt_chal_in->data, /* input */ + dc->sess_key, /* input */ + 1); + + des_crypt112(dc->srv_chal.data, /* output */ + srv_chal_in->data, /* input */ + dc->sess_key, /* input */ + 1); + + /* Seed is the client chal. */ + memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8); +} /**************************************************************************** Setup the session key and the client and server creds in dc. @@ -63,10 +115,10 @@ static void creds_init_64(struct dcinfo *dc, /* debug output */ DEBUG(5,("creds_init_64\n")); - DEBUG(5,(" clnt_chal_in: %s\n", credstr(clnt_chal_in->data))); - DEBUG(5,(" srv_chal_in : %s\n", credstr(srv_chal_in->data))); - DEBUG(5,(" clnt+srv : %s\n", credstr(sum2))); - DEBUG(5,(" sess_key_out : %s\n", credstr(dc->sess_key))); + DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data))); + DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data))); + DEBUG(5,("\tclnt+srv : %s\n", credstr(sum2))); + DEBUG(5,("\tsess_key_out : %s\n", credstr(dc->sess_key))); /* Generate the next client and server creds. */ @@ -120,21 +172,30 @@ static void creds_step(struct dcinfo *dc) Create a server credential struct. ****************************************************************************/ -void creds_server_init(struct dcinfo *dc, +void creds_server_init(uint32 neg_flags, + struct dcinfo *dc, DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, const char mach_pw[16], DOM_CHAL *init_chal_out) { + DEBUG(10,("creds_server_init: neg_flags : %x\n", (unsigned int)neg_flags)); DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) )); DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) )); dump_data_pw("creds_server_init: machine pass", (const unsigned char *)mach_pw, 16); /* Generate the session key and the next client and server creds. */ - creds_init_64(dc, + if (neg_flags & NETLOGON_NEG_128BIT) { + creds_init_128(dc, clnt_chal, srv_chal, mach_pw); + } else { + creds_init_64(dc, + clnt_chal, + srv_chal, + mach_pw); + } dump_data_pw("creds_server_init: session key", dc->sess_key, 16); @@ -213,7 +274,8 @@ BOOL creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRE Create a client credential struct. ****************************************************************************/ -void creds_client_init(struct dcinfo *dc, +void creds_client_init(uint32 neg_flags, + struct dcinfo *dc, DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, const unsigned char mach_pw[16], @@ -221,15 +283,23 @@ void creds_client_init(struct dcinfo *dc, { dc->sequence = time(NULL); + DEBUG(10,("creds_client_init: neg_flags : %x\n", (unsigned int)neg_flags)); DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) )); DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) )); dump_data_pw("creds_client_init: machine pass", (const unsigned char *)mach_pw, 16); /* Generate the session key and the next client and server creds. */ - creds_init_64(dc, + if (neg_flags & NETLOGON_NEG_128BIT) { + creds_init_128(dc, + clnt_chal, + srv_chal, + mach_pw); + } else { + creds_init_64(dc, clnt_chal, srv_chal, mach_pw); + } dump_data_pw("creds_client_init: session key", dc->sess_key, 16); diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 3dc26f61c9..7798519103 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -301,7 +301,8 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, } /* Calculate the session key and client credentials */ - creds_client_init(dc, + creds_client_init(*neg_flags_inout, + dc, &clnt_chal_send, &srv_chal_recv, machine_pwd, diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 97e19e6cb7..52f2c2e34c 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -338,7 +338,8 @@ NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u) } /* From the client / server challenges and md4 password, generate sess key */ - creds_server_init(p->dc, + creds_server_init(0, /* No neg flags. */ + p->dc, &p->dc->clnt_chal, /* Stored client chal. */ &p->dc->srv_chal, /* Stored server chal. */ (const char *)p->dc->mach_pw, @@ -415,7 +416,8 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) } /* From the client / server challenges and md4 password, generate sess key */ - creds_server_init(p->dc, + creds_server_init(q_u->clnt_flgs.neg_flags, + p->dc, &p->dc->clnt_chal, /* Stored client chal. */ &p->dc->srv_chal, /* Stored server chal. */ (const char *)p->dc->mach_pw, -- cgit