00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025
00026
00027
00028
00029 DATA_BLOB spnego_gen_negTokenInit(char guid[16],
00030 const char *OIDs[],
00031 const char *principal)
00032 {
00033 int i;
00034 ASN1_DATA data;
00035 DATA_BLOB ret;
00036
00037 memset(&data, 0, sizeof(data));
00038
00039 asn1_write(&data, guid, 16);
00040 asn1_push_tag(&data,ASN1_APPLICATION(0));
00041 asn1_write_OID(&data,OID_SPNEGO);
00042 asn1_push_tag(&data,ASN1_CONTEXT(0));
00043 asn1_push_tag(&data,ASN1_SEQUENCE(0));
00044
00045 asn1_push_tag(&data,ASN1_CONTEXT(0));
00046 asn1_push_tag(&data,ASN1_SEQUENCE(0));
00047 for (i=0; OIDs[i]; i++) {
00048 asn1_write_OID(&data,OIDs[i]);
00049 }
00050 asn1_pop_tag(&data);
00051 asn1_pop_tag(&data);
00052
00053 asn1_push_tag(&data, ASN1_CONTEXT(3));
00054 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00055 asn1_push_tag(&data, ASN1_CONTEXT(0));
00056 asn1_write_GeneralString(&data,principal);
00057 asn1_pop_tag(&data);
00058 asn1_pop_tag(&data);
00059 asn1_pop_tag(&data);
00060
00061 asn1_pop_tag(&data);
00062 asn1_pop_tag(&data);
00063
00064 asn1_pop_tag(&data);
00065
00066 if (data.has_error) {
00067 DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
00068 asn1_free(&data);
00069 }
00070
00071 ret = data_blob(data.data, data.length);
00072 asn1_free(&data);
00073
00074 return ret;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084 DATA_BLOB gen_negTokenInit(const char *OID, DATA_BLOB blob)
00085 {
00086 ASN1_DATA data;
00087 DATA_BLOB ret;
00088
00089 memset(&data, 0, sizeof(data));
00090
00091 asn1_push_tag(&data, ASN1_APPLICATION(0));
00092 asn1_write_OID(&data,OID_SPNEGO);
00093 asn1_push_tag(&data, ASN1_CONTEXT(0));
00094 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00095
00096 asn1_push_tag(&data, ASN1_CONTEXT(0));
00097 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00098 asn1_write_OID(&data, OID);
00099 asn1_pop_tag(&data);
00100 asn1_pop_tag(&data);
00101
00102 asn1_push_tag(&data, ASN1_CONTEXT(2));
00103 asn1_write_OctetString(&data,blob.data,blob.length);
00104 asn1_pop_tag(&data);
00105
00106 asn1_pop_tag(&data);
00107 asn1_pop_tag(&data);
00108
00109 asn1_pop_tag(&data);
00110
00111 if (data.has_error) {
00112 DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
00113 asn1_free(&data);
00114 }
00115
00116 ret = data_blob(data.data, data.length);
00117 asn1_free(&data);
00118
00119 return ret;
00120 }
00121
00122
00123
00124
00125
00126 BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
00127 char *OIDs[ASN1_MAX_OIDS],
00128 char **principal)
00129 {
00130 int i;
00131 BOOL ret;
00132 ASN1_DATA data;
00133
00134 asn1_load(&data, blob);
00135
00136 asn1_start_tag(&data,ASN1_APPLICATION(0));
00137 asn1_check_OID(&data,OID_SPNEGO);
00138 asn1_start_tag(&data,ASN1_CONTEXT(0));
00139 asn1_start_tag(&data,ASN1_SEQUENCE(0));
00140
00141 asn1_start_tag(&data,ASN1_CONTEXT(0));
00142 asn1_start_tag(&data,ASN1_SEQUENCE(0));
00143 for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
00144 char *oid_str = NULL;
00145 asn1_read_OID(&data,&oid_str);
00146 OIDs[i] = oid_str;
00147 }
00148 OIDs[i] = NULL;
00149 asn1_end_tag(&data);
00150 asn1_end_tag(&data);
00151
00152 *principal = NULL;
00153 if (asn1_tag_remaining(&data) > 0) {
00154 asn1_start_tag(&data, ASN1_CONTEXT(3));
00155 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00156 asn1_start_tag(&data, ASN1_CONTEXT(0));
00157 asn1_read_GeneralString(&data,principal);
00158 asn1_end_tag(&data);
00159 asn1_end_tag(&data);
00160 asn1_end_tag(&data);
00161 }
00162
00163 asn1_end_tag(&data);
00164 asn1_end_tag(&data);
00165
00166 asn1_end_tag(&data);
00167
00168 ret = !data.has_error;
00169 if (data.has_error) {
00170 int j;
00171 SAFE_FREE(*principal);
00172 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
00173 SAFE_FREE(OIDs[j]);
00174 }
00175 }
00176
00177 asn1_free(&data);
00178 return ret;
00179 }
00180
00181
00182
00183
00184 DATA_BLOB gen_negTokenTarg(const char *OIDs[], DATA_BLOB blob)
00185 {
00186 int i;
00187 ASN1_DATA data;
00188 DATA_BLOB ret;
00189
00190 memset(&data, 0, sizeof(data));
00191
00192 asn1_push_tag(&data, ASN1_APPLICATION(0));
00193 asn1_write_OID(&data,OID_SPNEGO);
00194 asn1_push_tag(&data, ASN1_CONTEXT(0));
00195 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00196
00197 asn1_push_tag(&data, ASN1_CONTEXT(0));
00198 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00199 for (i=0; OIDs[i]; i++) {
00200 asn1_write_OID(&data,OIDs[i]);
00201 }
00202 asn1_pop_tag(&data);
00203 asn1_pop_tag(&data);
00204
00205 asn1_push_tag(&data, ASN1_CONTEXT(2));
00206 asn1_write_OctetString(&data,blob.data,blob.length);
00207 asn1_pop_tag(&data);
00208
00209 asn1_pop_tag(&data);
00210 asn1_pop_tag(&data);
00211
00212 asn1_pop_tag(&data);
00213
00214 if (data.has_error) {
00215 DEBUG(1,("Failed to build negTokenTarg at offset %d\n", (int)data.ofs));
00216 asn1_free(&data);
00217 }
00218
00219 ret = data_blob(data.data, data.length);
00220 asn1_free(&data);
00221
00222 return ret;
00223 }
00224
00225
00226
00227
00228 BOOL parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *secblob)
00229 {
00230 int i;
00231 ASN1_DATA data;
00232
00233 asn1_load(&data, blob);
00234 asn1_start_tag(&data, ASN1_APPLICATION(0));
00235 asn1_check_OID(&data,OID_SPNEGO);
00236 asn1_start_tag(&data, ASN1_CONTEXT(0));
00237 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00238
00239 asn1_start_tag(&data, ASN1_CONTEXT(0));
00240 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00241 for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
00242 char *oid_str = NULL;
00243 asn1_read_OID(&data,&oid_str);
00244 OIDs[i] = oid_str;
00245 }
00246 OIDs[i] = NULL;
00247 asn1_end_tag(&data);
00248 asn1_end_tag(&data);
00249
00250 asn1_start_tag(&data, ASN1_CONTEXT(2));
00251 asn1_read_OctetString(&data,secblob);
00252 asn1_end_tag(&data);
00253
00254 asn1_end_tag(&data);
00255 asn1_end_tag(&data);
00256
00257 asn1_end_tag(&data);
00258
00259 if (data.has_error) {
00260 int j;
00261 data_blob_free(secblob);
00262 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
00263 SAFE_FREE(OIDs[j]);
00264 }
00265 DEBUG(1,("Failed to parse negTokenTarg at offset %d\n", (int)data.ofs));
00266 asn1_free(&data);
00267 return False;
00268 }
00269
00270 asn1_free(&data);
00271 return True;
00272 }
00273
00274
00275
00276
00277 DATA_BLOB spnego_gen_krb5_wrap(const DATA_BLOB ticket, const uint8 tok_id[2])
00278 {
00279 ASN1_DATA data;
00280 DATA_BLOB ret;
00281
00282 memset(&data, 0, sizeof(data));
00283
00284 asn1_push_tag(&data, ASN1_APPLICATION(0));
00285 asn1_write_OID(&data, OID_KERBEROS5);
00286
00287 asn1_write(&data, tok_id, 2);
00288 asn1_write(&data, ticket.data, ticket.length);
00289 asn1_pop_tag(&data);
00290
00291 if (data.has_error) {
00292 DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data.ofs));
00293 asn1_free(&data);
00294 }
00295
00296 ret = data_blob(data.data, data.length);
00297 asn1_free(&data);
00298
00299 return ret;
00300 }
00301
00302
00303
00304
00305 BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
00306 {
00307 BOOL ret;
00308 ASN1_DATA data;
00309 int data_remaining;
00310
00311 asn1_load(&data, blob);
00312 asn1_start_tag(&data, ASN1_APPLICATION(0));
00313 asn1_check_OID(&data, OID_KERBEROS5);
00314
00315 data_remaining = asn1_tag_remaining(&data);
00316
00317 if (data_remaining < 3) {
00318 data.has_error = True;
00319 } else {
00320 asn1_read(&data, tok_id, 2);
00321 data_remaining -= 2;
00322 *ticket = data_blob(NULL, data_remaining);
00323 asn1_read(&data, ticket->data, ticket->length);
00324 }
00325
00326 asn1_end_tag(&data);
00327
00328 ret = !data.has_error;
00329
00330 if (data.has_error) {
00331 data_blob_free(ticket);
00332 }
00333
00334 asn1_free(&data);
00335
00336 return ret;
00337 }
00338
00339
00340
00341
00342
00343
00344 int spnego_gen_negTokenTarg(const char *principal, int time_offset,
00345 DATA_BLOB *targ,
00346 DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
00347 time_t *expire_time)
00348 {
00349 int retval;
00350 DATA_BLOB tkt, tkt_wrapped;
00351 const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
00352
00353
00354 retval = cli_krb5_get_ticket(principal, time_offset,
00355 &tkt, session_key_krb5, extra_ap_opts, NULL,
00356 expire_time);
00357
00358 if (retval)
00359 return retval;
00360
00361
00362 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
00363
00364
00365 *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
00366
00367 data_blob_free(&tkt_wrapped);
00368 data_blob_free(&tkt);
00369
00370 return retval;
00371 }
00372
00373
00374
00375
00376
00377 BOOL spnego_parse_challenge(const DATA_BLOB blob,
00378 DATA_BLOB *chal1, DATA_BLOB *chal2)
00379 {
00380 BOOL ret;
00381 ASN1_DATA data;
00382
00383 ZERO_STRUCTP(chal1);
00384 ZERO_STRUCTP(chal2);
00385
00386 asn1_load(&data, blob);
00387 asn1_start_tag(&data,ASN1_CONTEXT(1));
00388 asn1_start_tag(&data,ASN1_SEQUENCE(0));
00389
00390 asn1_start_tag(&data,ASN1_CONTEXT(0));
00391 asn1_check_enumerated(&data,1);
00392 asn1_end_tag(&data);
00393
00394 asn1_start_tag(&data,ASN1_CONTEXT(1));
00395 asn1_check_OID(&data, OID_NTLMSSP);
00396 asn1_end_tag(&data);
00397
00398 asn1_start_tag(&data,ASN1_CONTEXT(2));
00399 asn1_read_OctetString(&data, chal1);
00400 asn1_end_tag(&data);
00401
00402
00403 if (asn1_tag_remaining(&data)) {
00404 asn1_start_tag(&data,ASN1_CONTEXT(3));
00405 asn1_read_OctetString(&data, chal2);
00406 asn1_end_tag(&data);
00407 }
00408
00409 asn1_end_tag(&data);
00410 asn1_end_tag(&data);
00411
00412 ret = !data.has_error;
00413
00414 if (data.has_error) {
00415 data_blob_free(chal1);
00416 data_blob_free(chal2);
00417 }
00418
00419 asn1_free(&data);
00420 return ret;
00421 }
00422
00423
00424
00425
00426
00427 DATA_BLOB spnego_gen_auth(DATA_BLOB blob)
00428 {
00429 ASN1_DATA data;
00430 DATA_BLOB ret;
00431
00432 memset(&data, 0, sizeof(data));
00433
00434 asn1_push_tag(&data, ASN1_CONTEXT(1));
00435 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00436 asn1_push_tag(&data, ASN1_CONTEXT(2));
00437 asn1_write_OctetString(&data,blob.data,blob.length);
00438 asn1_pop_tag(&data);
00439 asn1_pop_tag(&data);
00440 asn1_pop_tag(&data);
00441
00442 ret = data_blob(data.data, data.length);
00443
00444 asn1_free(&data);
00445
00446 return ret;
00447 }
00448
00449
00450
00451
00452 BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
00453 {
00454 ASN1_DATA data;
00455
00456 asn1_load(&data, blob);
00457 asn1_start_tag(&data, ASN1_CONTEXT(1));
00458 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00459 asn1_start_tag(&data, ASN1_CONTEXT(2));
00460 asn1_read_OctetString(&data,auth);
00461 asn1_end_tag(&data);
00462 asn1_end_tag(&data);
00463 asn1_end_tag(&data);
00464
00465 if (data.has_error) {
00466 DEBUG(3,("spnego_parse_auth failed at %d\n", (int)data.ofs));
00467 data_blob_free(auth);
00468 asn1_free(&data);
00469 return False;
00470 }
00471
00472 asn1_free(&data);
00473 return True;
00474 }
00475
00476
00477
00478
00479 DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status,
00480 const char *mechOID)
00481 {
00482 ASN1_DATA data;
00483 DATA_BLOB ret;
00484 uint8 negResult;
00485
00486 if (NT_STATUS_IS_OK(nt_status)) {
00487 negResult = SPNEGO_NEG_RESULT_ACCEPT;
00488 } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00489 negResult = SPNEGO_NEG_RESULT_INCOMPLETE;
00490 } else {
00491 negResult = SPNEGO_NEG_RESULT_REJECT;
00492 }
00493
00494 ZERO_STRUCT(data);
00495
00496 asn1_push_tag(&data, ASN1_CONTEXT(1));
00497 asn1_push_tag(&data, ASN1_SEQUENCE(0));
00498 asn1_push_tag(&data, ASN1_CONTEXT(0));
00499 asn1_write_enumerated(&data, negResult);
00500 asn1_pop_tag(&data);
00501
00502 if (reply->data != NULL) {
00503 asn1_push_tag(&data,ASN1_CONTEXT(1));
00504 asn1_write_OID(&data, mechOID);
00505 asn1_pop_tag(&data);
00506
00507 asn1_push_tag(&data,ASN1_CONTEXT(2));
00508 asn1_write_OctetString(&data, reply->data, reply->length);
00509 asn1_pop_tag(&data);
00510 }
00511
00512 asn1_pop_tag(&data);
00513 asn1_pop_tag(&data);
00514
00515 ret = data_blob(data.data, data.length);
00516 asn1_free(&data);
00517 return ret;
00518 }
00519
00520
00521
00522
00523 BOOL spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status,
00524 DATA_BLOB *auth)
00525 {
00526 ASN1_DATA data;
00527 uint8 negResult;
00528
00529 if (NT_STATUS_IS_OK(nt_status)) {
00530 negResult = SPNEGO_NEG_RESULT_ACCEPT;
00531 } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00532 negResult = SPNEGO_NEG_RESULT_INCOMPLETE;
00533 } else {
00534 negResult = SPNEGO_NEG_RESULT_REJECT;
00535 }
00536
00537 asn1_load(&data, blob);
00538 asn1_start_tag(&data, ASN1_CONTEXT(1));
00539 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00540 asn1_start_tag(&data, ASN1_CONTEXT(0));
00541 asn1_check_enumerated(&data, negResult);
00542 asn1_end_tag(&data);
00543
00544 if (negResult == SPNEGO_NEG_RESULT_INCOMPLETE) {
00545 asn1_start_tag(&data,ASN1_CONTEXT(1));
00546 asn1_check_OID(&data, OID_NTLMSSP);
00547 asn1_end_tag(&data);
00548
00549 asn1_start_tag(&data,ASN1_CONTEXT(2));
00550 asn1_read_OctetString(&data, auth);
00551 asn1_end_tag(&data);
00552 }
00553
00554 asn1_end_tag(&data);
00555 asn1_end_tag(&data);
00556
00557 if (data.has_error) {
00558 DEBUG(3,("spnego_parse_auth_response failed at %d\n", (int)data.ofs));
00559 asn1_free(&data);
00560 data_blob_free(auth);
00561 return False;
00562 }
00563
00564 asn1_free(&data);
00565 return True;
00566 }