diff options
Diffstat (limited to 'source4/utils/ntlm_auth.c')
-rw-r--r-- | source4/utils/ntlm_auth.c | 832 |
1 files changed, 70 insertions, 762 deletions
diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index d70b0b5d2b..7690a549f7 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -34,7 +34,6 @@ enum stdio_helper_mode { SQUID_2_5_BASIC, SQUID_2_5_NTLMSSP, NTLMSSP_CLIENT_1, - GSS_SPNEGO, GSS_SPNEGO_CLIENT, NTLM_SERVER_1, NUM_HELPER_MODES @@ -53,14 +52,8 @@ static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, char *buf, int length); -static void manage_client_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); - -static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); - -static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_gensec_client_request (enum stdio_helper_mode stdio_helper_mode, + char *buf, int length); static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode, char *buf, int length); @@ -73,9 +66,8 @@ static const struct { { SQUID_2_4_BASIC, "squid-2.4-basic", manage_squid_basic_request}, { SQUID_2_5_BASIC, "squid-2.5-basic", manage_squid_basic_request}, { SQUID_2_5_NTLMSSP, "squid-2.5-ntlmssp", manage_squid_ntlmssp_request}, - { NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_client_ntlmssp_request}, - { GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request}, - { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request}, + { NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_gensec_client_request}, + { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gensec_client_request}, { NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request}, { NUM_HELPER_MODES, NULL, NULL} }; @@ -218,52 +210,6 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *u return nt_status; } -static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntlmssp_state) -{ - NTSTATUS status; - if ( (opt_username == NULL) || (opt_domain == NULL) ) { - DEBUG(1, ("Need username and domain for NTLMSSP\n")); - return status; - } - - status = ntlmssp_client_start(client_ntlmssp_state); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Could not start NTLMSSP client: %s\n", - nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); - return status; - } - - status = ntlmssp_set_username(*client_ntlmssp_state, opt_username); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Could not set username: %s\n", - nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); - return status; - } - - status = ntlmssp_set_domain(*client_ntlmssp_state, opt_domain); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Could not set domain: %s\n", - nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); - return status; - } - - status = ntlmssp_set_password(*client_ntlmssp_state, opt_password); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Could not set password: %s\n", - nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); - return status; - } - return NT_STATUS_OK; -} - static NTSTATUS ntlm_auth_start_ntlmssp_server(struct ntlmssp_state **ntlmssp_state) { NTSTATUS status = ntlmssp_server_start(ntlmssp_state); @@ -367,102 +313,6 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod data_blob_free(&request); } -static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) -{ - static struct ntlmssp_state *ntlmssp_state = NULL; - DATA_BLOB request, reply; - NTSTATUS nt_status; - BOOL first = False; - - if (strlen(buf) < 2) { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if (strlen(buf) > 3) { - request = base64_decode_data_blob(buf + 3); - } else { - request = data_blob(NULL, 0); - } - - if (strncmp(buf, "PW ", 3) == 0) { - /* We asked for a password and obviously got it :-) */ - - opt_password = strndup((const char *)request.data, request.length); - - if (opt_password == NULL) { - DEBUG(1, ("Out of memory\n")); - x_fprintf(x_stdout, "BH\n"); - data_blob_free(&request); - return; - } - - x_fprintf(x_stdout, "OK\n"); - data_blob_free(&request); - return; - } - - if (opt_password == NULL) { - - /* Request a password from the calling process. After - sending it, the calling process should retry asking for the negotiate. */ - - DEBUG(10, ("Requesting password\n")); - x_fprintf(x_stdout, "PW\n"); - return; - } - - if (strncmp(buf, "YR", 2) == 0) { - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); - } else if (strncmp(buf, "TT", 2) == 0) { - - } else { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if (!ntlmssp_state) { - if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_client(&ntlmssp_state))) { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); - return; - } - first = True; - } - - DEBUG(10, ("got NTLMSSP packet:\n")); - dump_data(10, (const char *)request.data, request.length); - - nt_status = ntlmssp_update(ntlmssp_state, NULL, request, &reply); - - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - char *reply_base64 = base64_encode_data_blob(reply); - if (first) { - x_fprintf(x_stdout, "YR %s\n", reply_base64); - } else { - x_fprintf(x_stdout, "KK %s\n", reply_base64); - } - SAFE_FREE(reply_base64); - data_blob_free(&reply); - DEBUG(10, ("NTLMSSP challenge\n")); - } else if (NT_STATUS_IS_OK(nt_status)) { - x_fprintf(x_stdout, "AF\n"); - DEBUG(10, ("NTLMSSP OK!\n")); - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); - } else { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); - DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); - } - - data_blob_free(&request); -} - static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length) { @@ -490,654 +340,111 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, } } -static void offer_gss_spnego_mechs(void) { - - DATA_BLOB token; - struct spnego_data spnego; - ssize_t len; - char *reply_base64; - - pstring principal; - pstring myname_lower; - - ZERO_STRUCT(spnego); - - pstrcpy(myname_lower, global_myname()); - strlower_m(myname_lower); - - pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm()); - - /* Server negTokenInit (mech offerings) */ - spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 3); -#ifdef HAVE_KRB5 - spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); - spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); - spnego.negTokenInit.mechTypes[2] = NULL; -#else - spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); - spnego.negTokenInit.mechTypes[1] = NULL; -#endif - - - spnego.negTokenInit.mechListMIC = data_blob(principal, - strlen(principal)); - - len = write_spnego_data(&token, &spnego); - free_spnego_data(&spnego); - - if (len == -1) { - DEBUG(1, ("Could not write SPNEGO data blob\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - reply_base64 = base64_encode_data_blob(token); - x_fprintf(x_stdout, "TT %s *\n", reply_base64); - - SAFE_FREE(reply_base64); - data_blob_free(&token); - DEBUG(10, ("sent SPNEGO negTokenInit\n")); - return; -} - -static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_gensec_client_request(enum stdio_helper_mode stdio_helper_mode, + char *buf, int length) { - static struct ntlmssp_state *ntlmssp_state = NULL; - struct spnego_data request, response; - DATA_BLOB token; - NTSTATUS status; - ssize_t len; - - char *user = NULL; - char *domain = NULL; - - const char *reply_code; - char *reply_base64; - pstring reply_argument; + DATA_BLOB in; + DATA_BLOB out; + char *out_base64; + static struct gensec_security gensec_state; + NTSTATUS nt_status; + BOOL first = False; if (strlen(buf) < 2) { - DEBUG(1, ("SPENGO query [%s] invalid", buf)); + DEBUG(1, ("query [%s] invalid", buf)); x_fprintf(x_stdout, "BH\n"); return; } - if (strncmp(buf, "YR", 2) == 0) { - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); - } else if (strncmp(buf, "KK", 2) == 0) { - - } else { - DEBUG(1, ("SPENGO query [%s] invalid", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if ( (strlen(buf) == 2)) { - - /* no client data, get the negTokenInit offering - mechanisms */ - - offer_gss_spnego_mechs(); - return; - } - - /* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */ - - if (strlen(buf) <= 3) { - DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - token = base64_decode_data_blob(buf + 3); - len = read_spnego_data(token, &request); - data_blob_free(&token); - - if (len == -1) { - DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if (request.type == SPNEGO_NEG_TOKEN_INIT) { - - /* Second request from Client. This is where the - client offers its mechanism to use. */ - - if ( (request.negTokenInit.mechTypes == NULL) || - (request.negTokenInit.mechTypes[0] == NULL) ) { - DEBUG(1, ("Client did not offer any mechanism")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) { - - if ( request.negTokenInit.mechToken.data == NULL ) { - DEBUG(1, ("Client did not provide NTLMSSP data\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if ( ntlmssp_state != NULL ) { - DEBUG(1, ("Client wants a new NTLMSSP challenge, but " - "already got one\n")); - x_fprintf(x_stdout, "BH\n"); - ntlmssp_end(&ntlmssp_state); - return; - } - - if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(status)); - return; - } - - DEBUG(10, ("got NTLMSSP packet:\n")); - dump_data(10, (const char *)request.negTokenInit.mechToken.data, - request.negTokenInit.mechToken.length); - - response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); - response.negTokenTarg.mechListMIC = data_blob(NULL, 0); - - status = ntlmssp_update(ntlmssp_state, - NULL, - request.negTokenInit.mechToken, - &response.negTokenTarg.responseToken); - } - -#ifdef HAVE_KRB5 - if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { - - char *principal; - DATA_BLOB auth_data; - DATA_BLOB ap_rep; - DATA_BLOB session_key; - - if ( request.negTokenInit.mechToken.data == NULL ) { - DEBUG(1, ("Client did not provide Kerberos data\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = strdup(OID_KERBEROS5_OLD); - response.negTokenTarg.mechListMIC = data_blob(NULL, 0); - response.negTokenTarg.responseToken = data_blob(NULL, 0); - - status = ads_verify_ticket(lp_realm(), - &request.negTokenInit.mechToken, - &principal, &auth_data, &ap_rep, - &session_key); - - /* Now in "principal" we have the name we are - authenticated as. */ - - if (NT_STATUS_IS_OK(status)) { - - domain = strchr(principal, '@'); - - if (domain == NULL) { - DEBUG(1, ("Did not get a valid principal " - "from ads_verify_ticket\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - *domain++ = '\0'; - domain = strdup(domain); - user = strdup(principal); - - data_blob_free(&ap_rep); - data_blob_free(&auth_data); - - SAFE_FREE(principal); - } - } -#endif - - } else { - - if ( (request.negTokenTarg.supportedMech == NULL) || - ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) { - /* Kerberos should never send a negTokenTarg, OID_NTLMSSP - is the only one we support that sends this stuff */ - DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n", - request.negTokenTarg.supportedMech)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - if (request.negTokenTarg.responseToken.data == NULL) { - DEBUG(1, ("Got a negTokenTarg without a responseToken!\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - status = ntlmssp_update(ntlmssp_state, - NULL, - request.negTokenTarg.responseToken, - &response.negTokenTarg.responseToken); - - response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); - response.negTokenTarg.mechListMIC = data_blob(NULL, 0); - - if (NT_STATUS_IS_OK(status)) { - user = strdup(ntlmssp_state->user); - domain = strdup(ntlmssp_state->domain); - ntlmssp_end(&ntlmssp_state); - } - } - - free_spnego_data(&request); - - if (NT_STATUS_IS_OK(status)) { - response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; - reply_code = "AF"; - pstr_sprintf(reply_argument, "%s\\%s", domain, user); - } else if (NT_STATUS_EQUAL(status, - NT_STATUS_MORE_PROCESSING_REQUIRED)) { - response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; - reply_code = "TT"; - pstr_sprintf(reply_argument, "*"); + if (strlen(buf) > 3) { + in = base64_decode_data_blob(buf + 3); } else { - response.negTokenTarg.negResult = SPNEGO_REJECT; - reply_code = "NA"; - pstrcpy(reply_argument, nt_errstr(status)); - } - - SAFE_FREE(user); - SAFE_FREE(domain); - - len = write_spnego_data(&token, &response); - free_spnego_data(&response); - - if (len == -1) { - DEBUG(1, ("Could not write SPNEGO data blob\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } - - reply_base64 = base64_encode_data_blob(token); - - x_fprintf(x_stdout, "%s %s %s\n", - reply_code, reply_base64, reply_argument); - - SAFE_FREE(reply_base64); - data_blob_free(&token); - - return; -} - -static struct ntlmssp_state *client_ntlmssp_state = NULL; - -static BOOL manage_client_ntlmssp_init(struct spnego_data spnego) -{ - NTSTATUS status; - DATA_BLOB null_blob = data_blob(NULL, 0); - DATA_BLOB to_server; - char *to_server_base64; - const char *my_mechs[] = {OID_NTLMSSP, NULL}; - - DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n")); - - if (client_ntlmssp_state != NULL) { - DEBUG(1, ("Request for initial SPNEGO request where " - "we already have a state\n")); - return False; - } - - if (!client_ntlmssp_state) { - if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_client(&client_ntlmssp_state))) { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(status)); - return False; - } - } - - - if (opt_password == NULL) { - - /* Request a password from the calling process. After - sending it, the calling process should retry with - the negTokenInit. */ - - DEBUG(10, ("Requesting password\n")); - x_fprintf(x_stdout, "PW\n"); - return True; - } - - spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = my_mechs; - spnego.negTokenInit.reqFlags = 0; - spnego.negTokenInit.mechListMIC = null_blob; - - status = ntlmssp_update(client_ntlmssp_state, - NULL, - null_blob, - &spnego.negTokenInit.mechToken); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n", - nt_errstr(status))); - ntlmssp_end(&client_ntlmssp_state); - return False; - } - - write_spnego_data(&to_server, &spnego); - data_blob_free(&spnego.negTokenInit.mechToken); - - to_server_base64 = base64_encode_data_blob(to_server); - data_blob_free(&to_server); - x_fprintf(x_stdout, "KK %s\n", to_server_base64); - SAFE_FREE(to_server_base64); - return True; -} - -static void manage_client_ntlmssp_targ(struct spnego_data spnego) -{ - NTSTATUS status; - DATA_BLOB null_blob = data_blob(NULL, 0); - DATA_BLOB request; - DATA_BLOB to_server; - char *to_server_base64; - - DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n")); - - if (client_ntlmssp_state == NULL) { - DEBUG(1, ("Got NTLMSSP tArg without a client state\n")); - x_fprintf(x_stdout, "BH\n"); - ntlmssp_end(&client_ntlmssp_state); - return; - } - - if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { - x_fprintf(x_stdout, "NA\n"); - ntlmssp_end(&client_ntlmssp_state); - return; - } - - if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) { - x_fprintf(x_stdout, "AF\n"); - ntlmssp_end(&client_ntlmssp_state); - return; - } - - status = ntlmssp_update(client_ntlmssp_state, - NULL, - spnego.negTokenTarg.responseToken, - &request); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from " - "ntlmssp_update, got: %s\n", - nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); - data_blob_free(&request); - ntlmssp_end(&client_ntlmssp_state); - return; - } - - spnego.type = SPNEGO_NEG_TOKEN_TARG; - spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; - spnego.negTokenTarg.supportedMech = OID_NTLMSSP; - spnego.negTokenTarg.responseToken = request; - spnego.negTokenTarg.mechListMIC = null_blob; - - write_spnego_data(&to_server, &spnego); - data_blob_free(&request); - - to_server_base64 = base64_encode_data_blob(to_server); - data_blob_free(&to_server); - x_fprintf(x_stdout, "KK %s\n", to_server_base64); - SAFE_FREE(to_server_base64); - return; -} - -#ifdef HAVE_KRB5 - -static BOOL manage_client_krb5_init(struct spnego_data spnego) -{ - char *principal; - DATA_BLOB tkt, to_server; - DATA_BLOB session_key_krb5 = data_blob(NULL, 0); - struct spnego_data reply; - char *reply_base64; - int retval; - - const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL}; - ssize_t len; - - if ( (spnego.negTokenInit.mechListMIC.data == NULL) || - (spnego.negTokenInit.mechListMIC.length == 0) ) { - DEBUG(1, ("Did not get a principal for krb5\n")); - return False; + in = data_blob(NULL, 0); } - principal = malloc(spnego.negTokenInit.mechListMIC.length+1); - - if (principal == NULL) { - DEBUG(1, ("Could not malloc principal\n")); - return False; - } - - memcpy(principal, spnego.negTokenInit.mechListMIC.data, - spnego.negTokenInit.mechListMIC.length); - principal[spnego.negTokenInit.mechListMIC.length] = '\0'; - - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5); - - if (retval) { - - pstring user; - - /* Let's try to first get the TGT, for that we need a - password. */ - - if (opt_password == NULL) { - DEBUG(10, ("Requesting password\n")); - x_fprintf(x_stdout, "PW\n"); - return True; - } - - pstr_sprintf(user, "%s@%s", opt_username, opt_domain); - - if ((retval = kerberos_kinit_password(user, opt_password, - 0, NULL))) { - DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval))); - return False; - } - - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5); - - if (retval) { - DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval))); - return False; - } - } - - data_blob_free(&session_key_krb5); - - ZERO_STRUCT(reply); - - reply.type = SPNEGO_NEG_TOKEN_INIT; - reply.negTokenInit.mechTypes = my_mechs; - reply.negTokenInit.reqFlags = 0; - reply.negTokenInit.mechToken = tkt; - reply.negTokenInit.mechListMIC = data_blob(NULL, 0); - - len = write_spnego_data(&to_server, &reply); - data_blob_free(&tkt); - - if (len == -1) { - DEBUG(1, ("Could not write SPNEGO data blob\n")); - return False; - } - - reply_base64 = base64_encode_data_blob(to_server); - x_fprintf(x_stdout, "KK %s *\n", reply_base64); - - SAFE_FREE(reply_base64); - data_blob_free(&to_server); - DEBUG(10, ("sent GSS-SPNEGO KERBEROS5 negTokenInit\n")); - return True; -} - -static void manage_client_krb5_targ(struct spnego_data spnego) -{ - switch (spnego.negTokenTarg.negResult) { - case SPNEGO_ACCEPT_INCOMPLETE: - DEBUG(1, ("Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE\n")); - x_fprintf(x_stdout, "BH\n"); - break; - case SPNEGO_ACCEPT_COMPLETED: - DEBUG(10, ("Accept completed\n")); - x_fprintf(x_stdout, "AF\n"); - break; - case SPNEGO_REJECT: - DEBUG(10, ("Rejected\n")); - x_fprintf(x_stdout, "NA\n"); - break; - default: - DEBUG(1, ("Got an invalid negTokenTarg\n")); - x_fprintf(x_stdout, "AF\n"); - } -} - -#endif - -static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) -{ - DATA_BLOB request; - struct spnego_data spnego; - ssize_t len; - - if (strlen(buf) <= 3) { - DEBUG(1, ("SPNEGO query [%s] too short\n", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - } - - request = base64_decode_data_blob(buf+3); - if (strncmp(buf, "PW ", 3) == 0) { /* We asked for a password and obviously got it :-) */ - opt_password = strndup((const char *)request.data, request.length); + opt_password = strndup((const char *)in.data, in.length); if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); x_fprintf(x_stdout, "BH\n"); - data_blob_free(&request); + data_blob_free(&in); return; } x_fprintf(x_stdout, "OK\n"); - data_blob_free(&request); + data_blob_free(&in); return; } - - if ( (strncmp(buf, "TT ", 3) != 0) && + if (strncmp(buf, "YR", 2) == 0) { + if (gensec_state.ops) { + gensec_state.ops->end(&gensec_state); + gensec_state.ops = NULL; + } + } else if ( (strncmp(buf, "TT ", 3) != 0) && (strncmp(buf, "AF ", 3) != 0) && (strncmp(buf, "NA ", 3) != 0) ) { DEBUG(1, ("SPNEGO request [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH\n"); - data_blob_free(&request); + data_blob_free(&in); return; } - /* So we got a server challenge to generate a SPNEGO - client-to-server request... */ - - len = read_spnego_data(request, &spnego); - data_blob_free(&request); - - if (len == -1) { - DEBUG(1, ("Could not read SPNEGO data for [%s]\n", buf)); - x_fprintf(x_stdout, "BH\n"); + if (!opt_password) { + x_fprintf(x_stdout, "PW\n"); + data_blob_free(&in); return; } - if (spnego.type == SPNEGO_NEG_TOKEN_INIT) { - - /* The server offers a list of mechanisms */ - - char **mechType = spnego.negTokenInit.mechTypes; - - while (*mechType != NULL) { - -#ifdef HAVE_KRB5 - if ( (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) || - (strcmp(*mechType, OID_KERBEROS5) == 0) ) { - if (manage_client_krb5_init(spnego)) - goto out; - } -#endif - - if (strcmp(*mechType, OID_NTLMSSP) == 0) { - if (manage_client_ntlmssp_init(spnego)) - goto out; - } - - mechType++; + /* setup gensec */ + if (!gensec_state.ops) { + if (stdio_helper_mode == GSS_SPNEGO_CLIENT) { + gensec_state.ops = gensec_security_by_oid(OID_SPNEGO); + } else if (stdio_helper_mode == NTLMSSP_CLIENT_1) { + gensec_state.ops = gensec_security_by_oid(OID_NTLMSSP); + } else { + exit(1); } + gensec_state.user.name = opt_username; + gensec_state.user.domain = opt_domain; + gensec_state.user.password = opt_password; + nt_status = gensec_state.ops->client_start(&gensec_state); - DEBUG(1, ("Server offered no compatible mechanism\n")); - x_fprintf(x_stdout, "BH\n"); - return; + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("SPENGO login failed to initialise: %s\n", nt_errstr(nt_status))); + x_fprintf(x_stdout, "BH\n"); + return; + } + if (!in.length) { + first = True; + } } + + /* update */ - if (spnego.type == SPNEGO_NEG_TOKEN_TARG) { - - if (spnego.negTokenTarg.supportedMech == NULL) { - /* On accept/reject Windows does not send the - mechanism anymore. Handle that here and - shut down the mechanisms. */ - - switch (spnego.negTokenTarg.negResult) { - case SPNEGO_ACCEPT_COMPLETED: - x_fprintf(x_stdout, "AF\n"); - break; - case SPNEGO_REJECT: - x_fprintf(x_stdout, "NA\n"); - break; - default: - DEBUG(1, ("Got a negTokenTarg with no mech and an " - "unknown negResult: %d\n", - spnego.negTokenTarg.negResult)); - x_fprintf(x_stdout, "BH\n"); - } - - ntlmssp_end(&client_ntlmssp_state); - goto out; - } + nt_status = gensec_state.ops->update(&gensec_state, NULL, in, &out); + + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - if (strcmp(spnego.negTokenTarg.supportedMech, - OID_NTLMSSP) == 0) { - manage_client_ntlmssp_targ(spnego); - goto out; + out_base64 = base64_encode_data_blob(out); + if (first) { + x_fprintf(x_stdout, "YR %s\n", out_base64); + } else { + x_fprintf(x_stdout, "KK %s\n", out_base64); } + SAFE_FREE(out_base64); -#if HAVE_KRB5 - if (strcmp(spnego.negTokenTarg.supportedMech, - OID_KERBEROS5_OLD) == 0) { - manage_client_krb5_targ(spnego); - goto out; - } -#endif + } else if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("SPENGO login failed: %s\n", nt_errstr(nt_status))); + x_fprintf(x_stdout, "BH\n"); + } else { + x_fprintf(x_stdout, "AF\n"); } - DEBUG(1, ("Got an SPNEGO token I could not handle [%s]!\n", buf)); - x_fprintf(x_stdout, "BH\n"); - return; - - out: - free_spnego_data(&spnego); return; } @@ -1428,6 +735,7 @@ enum { { "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"}, { "domain", 0, POPT_ARG_STRING, &opt_domain, OPT_DOMAIN, "domain name"}, { "workstation", 0, POPT_ARG_STRING, &opt_workstation, OPT_WORKSTATION, "workstation"}, + { "username", 0, POPT_ARG_STRING, &opt_username, OPT_PASSWORD, "Username"}, { "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"}, POPT_COMMON_SAMBA POPT_TABLEEND @@ -1469,6 +777,10 @@ enum { return 1; } + if (opt_domain == NULL) { + opt_domain = lp_workgroup(); + } + if (helper_protocol) { int i; for (i=0; i<NUM_HELPER_MODES; i++) { @@ -1492,10 +804,6 @@ enum { exit(1); } - if (opt_domain == NULL) { - opt_domain = lp_workgroup(); - } - if (opt_workstation == NULL) { opt_workstation = lp_netbios_name(); } |