Changeset 740 for vendor/current/source3/libsmb/clispnego.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libsmb/clispnego.c
r587 r740 5 5 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 6 6 Copyright (C) Luke Howard 2003 7 Copyright (C) Jeremy Allison 2010 7 8 8 9 This program is free software; you can redistribute it and/or modify … … 23 24 #include "../libcli/auth/spnego.h" 24 25 #include "smb_krb5.h" 25 26 /* 27 generate a negTokenInit packet given a GUID, a list of supported 28 OIDs (the mechanisms) and a principal name string 29 */ 30 DATA_BLOB spnego_gen_negTokenInit(char guid[16], 31 const char *OIDs[], 26 #include "../lib/util/asn1.h" 27 28 /* 29 generate a negTokenInit packet given a list of supported 30 OIDs (the mechanisms) a blob, and a principal name string 31 */ 32 33 DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx, 34 const char *OIDs[], 35 DATA_BLOB *psecblob, 32 36 const char *principal) 33 37 { … … 41 45 } 42 46 43 asn1_write(data, guid, 16);44 47 asn1_push_tag(data,ASN1_APPLICATION(0)); 45 48 asn1_write_OID(data,OID_SPNEGO); … … 55 58 asn1_pop_tag(data); 56 59 57 asn1_push_tag(data, ASN1_CONTEXT(3)); 58 asn1_push_tag(data, ASN1_SEQUENCE(0)); 59 asn1_push_tag(data, ASN1_CONTEXT(0)); 60 asn1_write_GeneralString(data,principal); 61 asn1_pop_tag(data); 62 asn1_pop_tag(data); 63 asn1_pop_tag(data); 60 if (psecblob && psecblob->length && psecblob->data) { 61 asn1_push_tag(data, ASN1_CONTEXT(2)); 62 asn1_write_OctetString(data,psecblob->data, 63 psecblob->length); 64 asn1_pop_tag(data); 65 } 66 67 if (principal) { 68 asn1_push_tag(data, ASN1_CONTEXT(3)); 69 asn1_push_tag(data, ASN1_SEQUENCE(0)); 70 asn1_push_tag(data, ASN1_CONTEXT(0)); 71 asn1_write_GeneralString(data,principal); 72 asn1_pop_tag(data); 73 asn1_pop_tag(data); 74 asn1_pop_tag(data); 75 } 64 76 65 77 asn1_pop_tag(data); … … 72 84 } 73 85 74 ret = data_blob(data->data, data->length); 75 asn1_free(data); 76 77 return ret; 78 } 79 80 /* 81 Generate a negTokenInit as used by the client side ... It has a mechType 82 (OID), and a mechToken (a security blob) ... 83 84 Really, we need to break out the NTLMSSP stuff as well, because it could be 85 raw in the packets! 86 */ 87 DATA_BLOB gen_negTokenInit(const char *OID, DATA_BLOB blob) 88 { 89 ASN1_DATA *data; 90 DATA_BLOB ret; 91 92 data = asn1_init(talloc_tos()); 93 if (data == NULL) { 94 return data_blob_null; 95 } 96 97 asn1_push_tag(data, ASN1_APPLICATION(0)); 98 asn1_write_OID(data,OID_SPNEGO); 99 asn1_push_tag(data, ASN1_CONTEXT(0)); 100 asn1_push_tag(data, ASN1_SEQUENCE(0)); 101 102 asn1_push_tag(data, ASN1_CONTEXT(0)); 103 asn1_push_tag(data, ASN1_SEQUENCE(0)); 104 asn1_write_OID(data, OID); 105 asn1_pop_tag(data); 106 asn1_pop_tag(data); 107 108 asn1_push_tag(data, ASN1_CONTEXT(2)); 109 asn1_write_OctetString(data,blob.data,blob.length); 110 asn1_pop_tag(data); 111 112 asn1_pop_tag(data); 113 asn1_pop_tag(data); 114 115 asn1_pop_tag(data); 116 117 if (data->has_error) { 118 DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data->ofs)); 119 } 120 121 ret = data_blob(data->data, data->length); 86 ret = data_blob_talloc(ctx, data->data, data->length); 122 87 asn1_free(data); 123 88 … … 129 94 OIDs (the mechanisms) and a principal name string 130 95 */ 131 bool spnego_parse_negTokenInit(DATA_BLOB blob, 96 bool spnego_parse_negTokenInit(TALLOC_CTX *ctx, 97 DATA_BLOB blob, 132 98 char *OIDs[ASN1_MAX_OIDS], 133 char **principal) 99 char **principal, 100 DATA_BLOB *secblob) 134 101 { 135 102 int i; … … 160 127 asn1_start_tag(data,ASN1_SEQUENCE(0)); 161 128 for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) { 162 const char *oid_str = NULL; 163 asn1_read_OID(data,talloc_autofree_context(),&oid_str); 164 OIDs[i] = CONST_DISCARD(char *, oid_str); 129 asn1_read_OID(data,ctx, &OIDs[i]); 165 130 } 166 131 OIDs[i] = NULL; … … 168 133 asn1_end_tag(data); 169 134 170 *principal = NULL; 135 if (principal) { 136 *principal = NULL; 137 } 138 if (secblob) { 139 *secblob = data_blob_null; 140 } 171 141 172 142 /* … … 191 161 192 162 if (asn1_peek_tag(data, ASN1_CONTEXT(2))) { 163 DATA_BLOB sblob = data_blob_null; 193 164 /* mechToken [2] OCTET STRING OPTIONAL */ 194 DATA_BLOB token;195 165 asn1_start_tag(data, ASN1_CONTEXT(2)); 196 asn1_read_OctetString(data, talloc_autofree_context(), 197 &token); 198 asn1_end_tag(data); 199 /* Throw away the token - not used. */ 200 data_blob_free(&token); 166 asn1_read_OctetString(data, ctx, &sblob); 167 asn1_end_tag(data); 168 if (secblob) { 169 *secblob = sblob; 170 } else { 171 data_blob_free(&sblob); 172 } 201 173 } 202 174 203 175 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) { 176 char *princ = NULL; 204 177 /* mechListMIC [3] OCTET STRING OPTIONAL */ 205 178 asn1_start_tag(data, ASN1_CONTEXT(3)); 206 179 asn1_start_tag(data, ASN1_SEQUENCE(0)); 207 180 asn1_start_tag(data, ASN1_CONTEXT(0)); 208 asn1_read_GeneralString(data,talloc_autofree_context(), 209 principal); 210 asn1_end_tag(data); 211 asn1_end_tag(data); 212 asn1_end_tag(data); 181 asn1_read_GeneralString(data, ctx, &princ); 182 asn1_end_tag(data); 183 asn1_end_tag(data); 184 asn1_end_tag(data); 185 if (principal) { 186 *principal = princ; 187 } else { 188 TALLOC_FREE(princ); 189 } 213 190 } 214 191 … … 221 198 if (data->has_error) { 222 199 int j; 223 TALLOC_FREE(*principal); 200 if (principal) { 201 TALLOC_FREE(*principal); 202 } 203 if (secblob) { 204 data_blob_free(secblob); 205 } 224 206 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) { 225 207 TALLOC_FREE(OIDs[j]); … … 232 214 233 215 /* 234 generate a negTokenTarg packet given a list of OIDs and a security blob235 */236 DATA_BLOB gen_negTokenTarg(const char *OIDs[], DATA_BLOB blob)237 {238 int i;239 ASN1_DATA *data;240 DATA_BLOB ret;241 242 data = asn1_init(talloc_tos());243 if (data == NULL) {244 return data_blob_null;245 }246 247 asn1_push_tag(data, ASN1_APPLICATION(0));248 asn1_write_OID(data,OID_SPNEGO);249 asn1_push_tag(data, ASN1_CONTEXT(0));250 asn1_push_tag(data, ASN1_SEQUENCE(0));251 252 asn1_push_tag(data, ASN1_CONTEXT(0));253 asn1_push_tag(data, ASN1_SEQUENCE(0));254 for (i=0; OIDs[i]; i++) {255 asn1_write_OID(data,OIDs[i]);256 }257 asn1_pop_tag(data);258 asn1_pop_tag(data);259 260 asn1_push_tag(data, ASN1_CONTEXT(2));261 asn1_write_OctetString(data,blob.data,blob.length);262 asn1_pop_tag(data);263 264 asn1_pop_tag(data);265 asn1_pop_tag(data);266 267 asn1_pop_tag(data);268 269 if (data->has_error) {270 DEBUG(1,("Failed to build negTokenTarg at offset %d\n", (int)data->ofs));271 }272 273 ret = data_blob(data->data, data->length);274 asn1_free(data);275 276 return ret;277 }278 279 /*280 parse a negTokenTarg packet giving a list of OIDs and a security blob281 */282 bool parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *secblob)283 {284 int i;285 ASN1_DATA *data;286 287 data = asn1_init(talloc_tos());288 if (data == NULL) {289 return false;290 }291 292 asn1_load(data, blob);293 asn1_start_tag(data, ASN1_APPLICATION(0));294 asn1_check_OID(data,OID_SPNEGO);295 asn1_start_tag(data, ASN1_CONTEXT(0));296 asn1_start_tag(data, ASN1_SEQUENCE(0));297 298 asn1_start_tag(data, ASN1_CONTEXT(0));299 asn1_start_tag(data, ASN1_SEQUENCE(0));300 for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {301 const char *oid_str = NULL;302 asn1_read_OID(data,talloc_autofree_context(),&oid_str);303 OIDs[i] = CONST_DISCARD(char *, oid_str);304 }305 OIDs[i] = NULL;306 asn1_end_tag(data);307 asn1_end_tag(data);308 309 /* Skip any optional req_flags that are sent per RFC 4178 */310 if (asn1_peek_tag(data, ASN1_CONTEXT(1))) {311 uint8 flags;312 313 asn1_start_tag(data, ASN1_CONTEXT(1));314 asn1_start_tag(data, ASN1_BIT_STRING);315 while (asn1_tag_remaining(data) > 0)316 asn1_read_uint8(data, &flags);317 asn1_end_tag(data);318 asn1_end_tag(data);319 }320 321 asn1_start_tag(data, ASN1_CONTEXT(2));322 asn1_read_OctetString(data,talloc_autofree_context(),secblob);323 asn1_end_tag(data);324 325 asn1_end_tag(data);326 asn1_end_tag(data);327 328 asn1_end_tag(data);329 330 if (data->has_error) {331 int j;332 data_blob_free(secblob);333 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {334 TALLOC_FREE(OIDs[j]);335 }336 DEBUG(1,("Failed to parse negTokenTarg at offset %d\n", (int)data->ofs));337 asn1_free(data);338 return False;339 }340 341 asn1_free(data);342 return True;343 }344 345 /*346 216 generate a krb5 GSS-API wrapper packet given a ticket 347 217 */ 348 DATA_BLOB spnego_gen_krb5_wrap( const DATA_BLOB ticket, const uint8 tok_id[2])218 DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8 tok_id[2]) 349 219 { 350 220 ASN1_DATA *data; … … 367 237 } 368 238 369 ret = data_blob (data->data, data->length);239 ret = data_blob_talloc(ctx, data->data, data->length); 370 240 asn1_free(data); 371 241 … … 376 246 parse a krb5 GSS-API wrapper packet giving a ticket 377 247 */ 378 bool spnego_parse_krb5_wrap( DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])248 bool spnego_parse_krb5_wrap(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2]) 379 249 { 380 250 bool ret; … … 398 268 asn1_read(data, tok_id, 2); 399 269 data_remaining -= 2; 400 *ticket = data_blob (NULL, data_remaining);270 *ticket = data_blob_talloc(ctx, NULL, data_remaining); 401 271 asn1_read(data, ticket->data, ticket->length); 402 272 } … … 417 287 418 288 /* 419 generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY 420 kerberos session setup 421 */ 422 int spnego_gen_negTokenTarg(const char *principal, int time_offset, 423 DATA_BLOB *targ, 289 generate a SPNEGO krb5 negTokenInit packet, ready for a EXTENDED_SECURITY 290 kerberos session setup 291 */ 292 int spnego_gen_krb5_negTokenInit(TALLOC_CTX *ctx, 293 const char *principal, int time_offset, 294 DATA_BLOB *targ, 424 295 DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, 425 296 time_t *expire_time) … … 430 301 431 302 /* get a kerberos ticket for the service and extract the session key */ 432 retval = cli_krb5_get_ticket( principal, time_offset,433 &tkt, session_key_krb5, extra_ap_opts, NULL,434 expire_time, NULL);435 436 if (retval) 303 retval = cli_krb5_get_ticket(ctx, principal, time_offset, 304 &tkt, session_key_krb5, 305 extra_ap_opts, NULL, 306 expire_time, NULL); 307 if (retval) { 437 308 return retval; 309 } 438 310 439 311 /* wrap that up in a nice GSS-API wrapping */ 440 tkt_wrapped = spnego_gen_krb5_wrap( tkt, TOK_ID_KRB_AP_REQ);312 tkt_wrapped = spnego_gen_krb5_wrap(ctx, tkt, TOK_ID_KRB_AP_REQ); 441 313 442 314 /* and wrap that in a shiny SPNEGO wrapper */ 443 *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);315 *targ = spnego_gen_negTokenInit(ctx, krb_mechs, &tkt_wrapped, NULL); 444 316 445 317 data_blob_free(&tkt_wrapped); … … 453 325 parse a spnego NTLMSSP challenge packet giving two security blobs 454 326 */ 455 bool spnego_parse_challenge( const DATA_BLOB blob,327 bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob, 456 328 DATA_BLOB *chal1, DATA_BLOB *chal2) 457 329 { … … 480 352 481 353 asn1_start_tag(data,ASN1_CONTEXT(2)); 482 asn1_read_OctetString(data, talloc_autofree_context(), chal1);354 asn1_read_OctetString(data, ctx, chal1); 483 355 asn1_end_tag(data); 484 356 … … 486 358 if (asn1_tag_remaining(data)) { 487 359 asn1_start_tag(data,ASN1_CONTEXT(3)); 488 asn1_read_OctetString(data, talloc_autofree_context(), chal2);360 asn1_read_OctetString(data, ctx, chal2); 489 361 asn1_end_tag(data); 490 362 } … … 508 380 generate a SPNEGO auth packet. This will contain the encrypted passwords 509 381 */ 510 DATA_BLOB spnego_gen_auth( DATA_BLOB blob)382 DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob) 511 383 { 512 384 ASN1_DATA *data; … … 526 398 asn1_pop_tag(data); 527 399 528 ret = data_blob (data->data, data->length);400 ret = data_blob_talloc(ctx, data->data, data->length); 529 401 530 402 asn1_free(data); … … 536 408 parse a SPNEGO auth packet. This contains the encrypted passwords 537 409 */ 538 bool spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth) 410 bool spnego_parse_auth_and_mic(TALLOC_CTX *ctx, DATA_BLOB blob, 411 DATA_BLOB *auth, DATA_BLOB *signature) 539 412 { 540 413 ssize_t len; … … 554 427 } 555 428 556 *auth = data_blob_talloc( talloc_tos(),429 *auth = data_blob_talloc(ctx, 557 430 token.negTokenTarg.responseToken.data, 558 431 token.negTokenTarg.responseToken.length); 432 433 if (!signature) { 434 goto done; 435 } 436 437 *signature = data_blob_talloc(ctx, 438 token.negTokenTarg.mechListMIC.data, 439 token.negTokenTarg.mechListMIC.length); 440 441 done: 559 442 spnego_free_data(&token); 560 443 … … 562 445 } 563 446 447 bool spnego_parse_auth(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *auth) 448 { 449 return spnego_parse_auth_and_mic(ctx, blob, auth, NULL); 450 } 451 564 452 /* 565 453 generate a minimal SPNEGO response packet. Doesn't contain much. 566 454 */ 567 DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status, 568 const char *mechOID) 455 DATA_BLOB spnego_gen_auth_response_and_mic(TALLOC_CTX *ctx, 456 NTSTATUS nt_status, 457 const char *mechOID, 458 DATA_BLOB *reply, 459 DATA_BLOB *mechlistMIC) 569 460 { 570 461 ASN1_DATA *data; … … 603 494 } 604 495 605 asn1_pop_tag(data); 606 asn1_pop_tag(data); 607 608 ret = data_blob(data->data, data->length); 496 if (mechlistMIC && mechlistMIC->data != NULL) { 497 asn1_push_tag(data, ASN1_CONTEXT(3)); 498 asn1_write_OctetString(data, 499 mechlistMIC->data, 500 mechlistMIC->length); 501 asn1_pop_tag(data); 502 } 503 504 asn1_pop_tag(data); 505 asn1_pop_tag(data); 506 507 ret = data_blob_talloc(ctx, data->data, data->length); 609 508 asn1_free(data); 610 509 return ret; 611 510 } 612 511 512 DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx, DATA_BLOB *reply, 513 NTSTATUS nt_status, const char *mechOID) 514 { 515 return spnego_gen_auth_response_and_mic(ctx, nt_status, 516 mechOID, reply, NULL); 517 } 518 613 519 /* 614 520 parse a SPNEGO auth packet. This contains the encrypted passwords 615 521 */ 616 bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status, 522 bool spnego_parse_auth_response(TALLOC_CTX *ctx, 523 DATA_BLOB blob, NTSTATUS nt_status, 617 524 const char *mechOID, 618 525 DATA_BLOB *auth) … … 650 557 if (asn1_tag_remaining(data)) { 651 558 asn1_start_tag(data,ASN1_CONTEXT(2)); 652 asn1_read_OctetString(data, talloc_autofree_context(), auth);559 asn1_read_OctetString(data, ctx, auth); 653 560 asn1_end_tag(data); 654 561 } … … 664 571 DATA_BLOB mechList = data_blob_null; 665 572 asn1_start_tag(data, ASN1_CONTEXT(3)); 666 asn1_read_OctetString(data, talloc_autofree_context(), &mechList);573 asn1_read_OctetString(data, ctx, &mechList); 667 574 asn1_end_tag(data); 668 575 data_blob_free(&mechList); … … 684 591 return True; 685 592 } 593 594 bool spnego_mech_list_blob(TALLOC_CTX *mem_ctx, 595 char **oid_list, DATA_BLOB *raw_data) 596 { 597 ASN1_DATA *data; 598 unsigned int idx; 599 600 if (!oid_list || !oid_list[0] || !raw_data) { 601 return false; 602 } 603 604 data = asn1_init(talloc_tos()); 605 if (data == NULL) { 606 return false; 607 } 608 609 asn1_push_tag(data, ASN1_SEQUENCE(0)); 610 for (idx = 0; oid_list[idx]; idx++) { 611 asn1_write_OID(data, oid_list[idx]); 612 } 613 asn1_pop_tag(data); 614 615 if (data->has_error) { 616 DEBUG(3, (__location__ " failed at %d\n", (int)data->ofs)); 617 asn1_free(data); 618 return false; 619 } 620 621 *raw_data = data_blob_talloc(mem_ctx, data->data, data->length); 622 if (!raw_data->data) { 623 DEBUG(3, (__location__": data_blob_talloc() failed!\n")); 624 asn1_free(data); 625 return false; 626 } 627 628 asn1_free(data); 629 return true; 630 }
Note:
See TracChangeset
for help on using the changeset viewer.