Author: gd Date: 2006-02-20 23:22:56 +0000 (Mon, 20 Feb 2006) New Revision: 13581
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=13581 Log: Correctly parse a non-null terminated, little-endian UCS2 string in the PAC_LOGON_NAME structure. This was broken on big-endian machines (Solaris SPARC and ppc). Fixes Bug #3330. Jerry, this should be in 3.0.21c. Guenther Modified: branches/SAMBA_3_0/source/include/authdata.h branches/SAMBA_3_0/source/libads/authdata.c branches/SAMBA_3_0/source/rpc_parse/parse_prs.c trunk/source/include/authdata.h trunk/source/libads/authdata.c trunk/source/rpc_parse/parse_prs.c Changeset: Modified: branches/SAMBA_3_0/source/include/authdata.h =================================================================== --- branches/SAMBA_3_0/source/include/authdata.h 2006-02-20 22:21:21 UTC (rev 13580) +++ branches/SAMBA_3_0/source/include/authdata.h 2006-02-20 23:22:56 UTC (rev 13581) @@ -42,7 +42,7 @@ typedef struct pac_logon_name { NTTIME logon_time; uint16 len; - uint16 *username; /* might not be null terminated, so not UNISTR */ + fstring username; } PAC_LOGON_NAME; typedef struct pac_signature_data { Modified: branches/SAMBA_3_0/source/libads/authdata.c =================================================================== --- branches/SAMBA_3_0/source/libads/authdata.c 2006-02-20 22:21:21 UTC (rev 13580) +++ branches/SAMBA_3_0/source/libads/authdata.c 2006-02-20 23:22:56 UTC (rev 13581) @@ -42,16 +42,7 @@ if (!prs_uint16("len", ps, depth, &logon_name->len)) return False; - if (UNMARSHALLING(ps) && logon_name->len) { - logon_name->username = PRS_ALLOC_MEM(ps, uint16, logon_name->len); - if (!logon_name->username) { - DEBUG(3, ("No memory available\n")); - return False; - } - } - - if (!prs_uint16s(True, "name", ps, depth, logon_name->username, - (logon_name->len / sizeof(uint16)))) + if (!prs_string_len("name", ps, depth, logon_name->username, logon_name->len)) return False; return True; @@ -891,8 +882,9 @@ nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } - rpcstr_pull(username, logon_name->username, sizeof(username), -1, STR_TERMINATE); + rpcstr_pull(username, logon_name->username, sizeof(username), logon_name->len, 0); + ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac); if (ret) { DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", Modified: branches/SAMBA_3_0/source/rpc_parse/parse_prs.c =================================================================== --- branches/SAMBA_3_0/source/rpc_parse/parse_prs.c 2006-02-20 22:21:21 UTC (rev 13580) +++ branches/SAMBA_3_0/source/rpc_parse/parse_prs.c 2006-02-20 23:22:56 UTC (rev 13581) @@ -1333,6 +1333,49 @@ } /******************************************************************* + Stream a null-terminated string of fixed len. + ********************************************************************/ + +BOOL prs_string_len(const char *name, prs_struct *ps, int depth, char *str, int len) +{ + char *q; + int i; + BOOL charmode = True; + + q = prs_mem_get(ps, len+1); + if (q == NULL) + return False; + + for(i = 0; i < len; i++) { + if (UNMARSHALLING(ps)) + str[i] = q[i]; + else + q[i] = str[i]; + } + + /* The terminating null. */ + str[i] = '\0'; + + if (MARSHALLING(ps)) { + q[i] = '\0'; + } + + ps->data_offset += len+1; + + DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); + if (charmode) { + print_asc(5, (unsigned char*)str, len); + } else { + for (i = 0; i < len; i++) + DEBUG(5,("%04x ", str[i])); + } + DEBUG(5,("\n")); + + return True; +} + + +/******************************************************************* prs_uint16 wrapper. Call this and it sets up a pointer to where the uint16 should be stored, or gets the size if reading. ********************************************************************/ Modified: trunk/source/include/authdata.h =================================================================== --- trunk/source/include/authdata.h 2006-02-20 22:21:21 UTC (rev 13580) +++ trunk/source/include/authdata.h 2006-02-20 23:22:56 UTC (rev 13581) @@ -42,7 +42,7 @@ typedef struct pac_logon_name { NTTIME logon_time; uint16 len; - uint16 *username; /* might not be null terminated, so not UNISTR */ + fstring username; } PAC_LOGON_NAME; typedef struct pac_signature_data { Modified: trunk/source/libads/authdata.c =================================================================== --- trunk/source/libads/authdata.c 2006-02-20 22:21:21 UTC (rev 13580) +++ trunk/source/libads/authdata.c 2006-02-20 23:22:56 UTC (rev 13581) @@ -42,16 +42,7 @@ if (!prs_uint16("len", ps, depth, &logon_name->len)) return False; - if (UNMARSHALLING(ps) && logon_name->len) { - logon_name->username = PRS_ALLOC_MEM(ps, uint16, logon_name->len); - if (!logon_name->username) { - DEBUG(3, ("No memory available\n")); - return False; - } - } - - if (!prs_uint16s(True, "name", ps, depth, logon_name->username, - (logon_name->len / sizeof(uint16)))) + if (!prs_string_len("name", ps, depth, logon_name->username, logon_name->len)) return False; return True; @@ -891,8 +882,9 @@ nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } - rpcstr_pull(username, logon_name->username, sizeof(username), -1, STR_TERMINATE); + rpcstr_pull(username, logon_name->username, sizeof(username), logon_name->len, 0); + ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac); if (ret) { DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", Modified: trunk/source/rpc_parse/parse_prs.c =================================================================== --- trunk/source/rpc_parse/parse_prs.c 2006-02-20 22:21:21 UTC (rev 13580) +++ trunk/source/rpc_parse/parse_prs.c 2006-02-20 23:22:56 UTC (rev 13581) @@ -1333,6 +1333,49 @@ } /******************************************************************* + Stream a null-terminated string of fixed len. + ********************************************************************/ + +BOOL prs_string_len(const char *name, prs_struct *ps, int depth, char *str, int len) +{ + char *q; + int i; + BOOL charmode = True; + + q = prs_mem_get(ps, len+1); + if (q == NULL) + return False; + + for(i = 0; i < len; i++) { + if (UNMARSHALLING(ps)) + str[i] = q[i]; + else + q[i] = str[i]; + } + + /* The terminating null. */ + str[i] = '\0'; + + if (MARSHALLING(ps)) { + q[i] = '\0'; + } + + ps->data_offset += len+1; + + DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); + if (charmode) { + print_asc(5, (unsigned char*)str, len); + } else { + for (i = 0; i < len; i++) + DEBUG(5,("%04x ", str[i])); + } + DEBUG(5,("\n")); + + return True; +} + + +/******************************************************************* prs_uint16 wrapper. Call this and it sets up a pointer to where the uint16 should be stored, or gets the size if reading. ********************************************************************/