From 6f9b901fa0db18faae603db67d8d31e229d92c27 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 30 Aug 2005 01:19:41 +0000 Subject: r9772: Make credentials callbacks more consistant with the abstraction function interface used in the credentials code. Fix bug in ntlm_auth, where we would overwrite the PW specified as a first input. (Reported and chased by Kai Blin , bug #3040) Andrew Bartlett (This used to be commit 04af95bd31de39ad6aff349a4838dd77cb300034) --- source4/gtk/common/credentials.c | 17 +----- source4/lib/cmdline/credentials.c | 9 +-- source4/lib/credentials.c | 99 ++++++++++++++++++++++++++++++--- source4/utils/ntlm_auth.c | 113 ++++++++++++++++++++++---------------- 4 files changed, 165 insertions(+), 73 deletions(-) (limited to 'source4') diff --git a/source4/gtk/common/credentials.c b/source4/gtk/common/credentials.c index ccc9759e8f..01132ec6bd 100644 --- a/source4/gtk/common/credentials.c +++ b/source4/gtk/common/credentials.c @@ -132,18 +132,7 @@ static const char *gtk_get_domain(struct cli_credentials *credentials) void cli_credentials_set_gtk_callbacks(struct cli_credentials *cred) { - if (cred->password_obtained <= CRED_CALLBACK) { - cred->password_cb = gtk_get_userpassword; - cred->password_obtained = CRED_CALLBACK; - } - - if (cred->username_obtained <= CRED_CALLBACK) { - cred->username_cb = gtk_get_username; - cred->username_obtained = CRED_CALLBACK; - } - - if (cred->domain_obtained <= CRED_CALLBACK) { - cred->domain_cb = gtk_get_domain; - cred->domain_obtained = CRED_CALLBACK; - } + cli_credentials_set_username_callback(cred, gtk_get_username); + cli_credentials_set_domain_callback(cred, gtk_get_domain); + cli_credentials_set_password_callback(cred, gtk_get_userpassword); } diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c index 7832e01e4b..f46a03b236 100644 --- a/source4/lib/cmdline/credentials.c +++ b/source4/lib/cmdline/credentials.c @@ -29,8 +29,8 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) { char *prompt; char *ret; - char *domain; - char *username; + const char *domain; + const char *username; TALLOC_CTX *mem_ctx = talloc_new(NULL); domain = cli_credentials_get_domain(credentials); @@ -51,8 +51,5 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) void cli_credentials_set_cmdline_callbacks(struct cli_credentials *cred) { - if (cred->password_obtained <= CRED_CALLBACK) { - cred->password_cb = cmdline_get_userpassword; - cred->password_obtained = CRED_CALLBACK; - } + cli_credentials_set_password_callback(cred, cmdline_get_userpassword); } diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 579f199d2e..162b52e5d0 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -77,7 +77,8 @@ const char *cli_credentials_get_username(struct cli_credentials *cred, TALLOC_CT return talloc_reference(mem_ctx, cred->username); } -BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_username(struct cli_credentials *cred, + const char *val, enum credentials_obtained obtained) { if (obtained >= cred->username_obtained) { cred->username = talloc_strdup(cred, val); @@ -88,6 +89,20 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, return False; } +BOOL cli_credentials_set_username_callback(struct cli_credentials *cred, + const char *(*username_cb) (struct cli_credentials *)) +{ + if (cred->username_obtained < CRED_CALLBACK) { + cred->username_cb = username_cb; + cred->username_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + + + /** * Obtain the client principal for this credentials context. * @param cred credentials context @@ -124,6 +139,18 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred, const char *val return False; } +BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred, + const char *(*principal_cb) (struct cli_credentials *)) +{ + if (cred->principal_obtained < CRED_CALLBACK) { + cred->principal_cb = principal_cb; + cred->principal_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) { if (cred->principal_obtained >= CRED_SPECIFIED) { @@ -154,7 +181,9 @@ const char *cli_credentials_get_password(struct cli_credentials *cred) return cred->password; } -BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_password(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->password_obtained) { cred->password = talloc_strdup(cred, val); @@ -167,6 +196,18 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, return False; } +BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, + const char *(*password_cb) (struct cli_credentials *)) +{ + if (cred->password_obtained < CRED_CALLBACK) { + cred->password_cb = password_cb; + cred->password_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the password for this credentials context. * @param cred credentials context @@ -375,7 +416,8 @@ int cli_credentials_new_ccache(struct cli_credentials *cred) return ret; } -int cli_credentials_get_ccache(struct cli_credentials *cred, struct ccache_container **ccc) +int cli_credentials_get_ccache(struct cli_credentials *cred, + struct ccache_container **ccc) { krb5_error_code ret; @@ -432,7 +474,9 @@ const char *cli_credentials_get_domain(struct cli_credentials *cred) } -BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_domain(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->domain_obtained) { cred->domain = talloc_strdup(cred, val); @@ -443,6 +487,18 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e return False; } +BOOL cli_credentials_set_domain_callback(struct cli_credentials *cred, + const char *(*domain_cb) (struct cli_credentials *)) +{ + if (cred->domain_obtained < CRED_CALLBACK) { + cred->domain_cb = domain_cb; + cred->domain_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the Kerberos realm for this credentials context. * @param cred credentials context @@ -467,7 +523,9 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) * Set the realm for this credentials context, and force it to * uppercase for the sainity of our local kerberos libraries */ -BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_realm(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->realm_obtained) { cred->realm = strupper_talloc(cred, val); @@ -478,6 +536,18 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en return False; } +BOOL cli_credentials_set_realm_callback(struct cli_credentials *cred, + const char *(*realm_cb) (struct cli_credentials *)) +{ + if (cred->realm_obtained < CRED_CALLBACK) { + cred->realm_cb = realm_cb; + cred->realm_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context. * @@ -495,7 +565,9 @@ const char *cli_credentials_get_workstation(struct cli_credentials *cred) return cred->workstation; } -BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_workstation(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->workstation_obtained) { cred->workstation = talloc_strdup(cred, val); @@ -506,6 +578,18 @@ BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *v return False; } +BOOL cli_credentials_set_workstation_callback(struct cli_credentials *cred, + const char *(*workstation_cb) (struct cli_credentials *)) +{ + if (cred->workstation_obtained < CRED_CALLBACK) { + cred->workstation_cb = workstation_cb; + cred->workstation_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Read a file descriptor, and parse it for a password (eg from a file or stdin) * @@ -514,7 +598,8 @@ BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *v * @param obtained This enum describes how 'specified' this password is */ -BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained) +BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, + int fd, enum credentials_obtained obtained) { char *p; char pass[128]; diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index b10d4af6ce..fe29cff021 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -292,13 +292,32 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, DATA_BLOB out = data_blob(NULL, 0); char *out_base64 = NULL; const char *reply_arg = NULL; - struct gensec_security **gensec_state = (struct gensec_security **)private; + struct gensec_ntlm_state { + struct gensec_security *gensec_state; + const char *set_password; + }; + struct gensec_ntlm_state *state; + NTSTATUS nt_status; BOOL first = False; const char *reply_code; struct cli_credentials *creds; TALLOC_CTX *mem_ctx; + + if (*private) { + state = *private; + } else { + state = talloc_zero(NULL, struct gensec_ntlm_state); + if (!state) { + mux_printf(mux_id, "BH No Memory\n"); + exit(1); + } + *private = state; + if (opt_password) { + state->set_password = opt_password; + } + } if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); @@ -313,9 +332,9 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } if (strncmp(buf, "YR", 2) == 0) { - if (gensec_state && *gensec_state) { - talloc_free(*gensec_state); - *gensec_state = NULL; + if (state->gensec_state) { + talloc_free(state->gensec_state); + state->gensec_state = NULL; } } else if ( (strncmp(buf, "OK", 2) == 0)) { /* do nothing */ @@ -334,42 +353,21 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } /* setup gensec */ - if (!(gensec_state && *gensec_state)) { + if (!(state->gensec_state)) { switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case NTLMSSP_CLIENT_1: /* setup the client side */ - nt_status = gensec_client_start(NULL, gensec_state, NULL); + nt_status = gensec_client_start(NULL, &state->gensec_state, NULL); if (!NT_STATUS_IS_OK(nt_status)) { exit(1); } - creds = cli_credentials_init(*gensec_state); - cli_credentials_set_conf(creds); - if (opt_username) { - cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED); - } - if (opt_domain) { - cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED); - } - if (opt_password) { - cli_credentials_set_password(creds, opt_password, CRED_SPECIFIED); - } else { - creds->password_obtained = CRED_CALLBACK; - creds->password_cb = get_password; - creds->priv_data = (void*)mux_id; - } - if (opt_workstation) { - cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); - } - - gensec_set_credentials(*gensec_state, creds); - break; case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: - if (!NT_STATUS_IS_OK(gensec_server_start(NULL, gensec_state, NULL))) { + if (!NT_STATUS_IS_OK(gensec_server_start(NULL, &state->gensec_state, NULL))) { exit(1); } break; @@ -377,10 +375,29 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, abort(); } + creds = cli_credentials_init(state->gensec_state); + cli_credentials_set_conf(creds); + if (opt_username) { + cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED); + } + if (opt_domain) { + cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED); + } + if (state->set_password) { + cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED); + } else { + cli_credentials_set_password_callback(creds, get_password); + creds->priv_data = (void*)mux_id; + } + if (opt_workstation) { + cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); + } + gensec_set_credentials(state->gensec_state, creds); + switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case GSS_SPNEGO_SERVER: - nt_status = gensec_start_mech_by_oid(*gensec_state, GENSEC_OID_SPNEGO); + nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO); if (!in.length) { first = True; } @@ -390,7 +407,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, first = True; } case SQUID_2_5_NTLMSSP: - nt_status = gensec_start_mech_by_oid(*gensec_state, GENSEC_OID_NTLMSSP); + nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP); break; default: abort(); @@ -401,32 +418,36 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, mux_printf(mux_id, "BH\n"); return; } + } + + /* update */ + mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx"); if (strncmp(buf, "PW ", 3) == 0) { - - cli_credentials_set_password((*gensec_state)->credentials, - talloc_strndup((*gensec_state), - (const char *)in.data, - in.length), + state->set_password = talloc_strndup(state, + (const char *)in.data, + in.length); + + cli_credentials_set_password(gensec_get_credentials(state->gensec_state), + state->set_password, CRED_SPECIFIED); mux_printf(mux_id, "OK\n"); data_blob_free(&in); + talloc_free(mem_ctx); return; } - /* update */ - mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx"); - if (strncmp(buf, "UG", 2) == 0) { int i; char *grouplist = NULL; struct auth_session_info *session_info; - if (!NT_STATUS_IS_OK(gensec_session_info(*gensec_state, &session_info))) { + if (!NT_STATUS_IS_OK(gensec_session_info(state->gensec_state, &session_info))) { DEBUG(1, ("gensec_session_info failed: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status)); data_blob_free(&in); + talloc_free(mem_ctx); return; } @@ -447,7 +468,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, return; } - nt_status = gensec_update(*gensec_state, mem_ctx, in, &out); + nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out); /* don't leak 'bad password'/'no such user' info to the network client */ nt_status = auth_nt_status_squash(nt_status); @@ -462,9 +483,9 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, reply_arg = "*"; if (first) { reply_code = "YR"; - } else if ((*gensec_state)->gensec_role == GENSEC_CLIENT) { + } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "KK"; - } else if ((*gensec_state)->gensec_role == GENSEC_SERVER) { + } else if (state->gensec_state->gensec_role == GENSEC_SERVER) { reply_code = "TT"; } else { abort(); @@ -483,10 +504,10 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, reply_code = "NA"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); - } else if /* OK */ ((*gensec_state)->gensec_role == GENSEC_SERVER) { + } else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) { struct auth_session_info *session_info; - nt_status = gensec_session_info(*gensec_state, &session_info); + nt_status = gensec_session_info(state->gensec_state, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { reply_code = "BH"; reply_arg = nt_errstr(nt_status); @@ -494,12 +515,12 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } else { reply_code = "AF"; - reply_arg = talloc_asprintf(*gensec_state, + reply_arg = talloc_asprintf(state->gensec_state, "%s%s%s", session_info->server_info->domain_name, lp_winbind_separator(), session_info->server_info->account_name); talloc_free(session_info); } - } else if ((*gensec_state)->gensec_role == GENSEC_CLIENT) { + } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "AF"; reply_arg = out_base64; } else { -- cgit