int cli_credentials_update_keytab(struct cli_credentials *cred) { krb5_error_code ret; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context); if (ret) { talloc_free(mem_ctx); return ret; } ret = cli_credentials_get_keytab(cred, &ktc); if (ret != 0) { talloc_free(mem_ctx); return ret; } ret = smb_krb5_update_keytab(mem_ctx, cred, smb_krb5_context, ktc); talloc_free(mem_ctx); return ret; }
int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc) { krb5_error_code ret; char *rand_string; struct ccache_container *ccc = talloc(cred, struct ccache_container); char *ccache_name; if (!ccc) { return ENOMEM; } rand_string = generate_random_str(NULL, 16); if (!rand_string) { talloc_free(ccc); return ENOMEM; } ccache_name = talloc_asprintf(ccc, "MEMORY:%s", rand_string); talloc_free(rand_string); if (!ccache_name) { talloc_free(ccc); return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); return ret; } talloc_reference(ccc, ccc->smb_krb5_context); ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache); if (ret) { DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", ccache_name, smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccache_name); talloc_free(ccc); return ret; } talloc_set_destructor(ccc, free_mccache); cred->ccache = ccc; talloc_steal(cred, ccc); talloc_free(ccache_name); if (_ccc) { *_ccc = ccc; } return ret; }
/* Get the keytab (actually, a container containing the krb5_keytab) * attached to this context. If this hasn't been done or set before, * it will be generated from the password. */ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct keytab_container **_ktc) { krb5_error_code ret; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; TALLOC_CTX *mem_ctx; if (cred->keytab_obtained >= (MAX(cred->principal_obtained, cred->username_obtained))) { *_ktc = cred->keytab; return 0; } if (cli_credentials_is_anonymous(cred)) { return EINVAL; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); if (ret) { return ret; } mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = smb_krb5_create_memory_keytab(mem_ctx, cred, smb_krb5_context, &ktc); if (ret) { talloc_free(mem_ctx); return ret; } cred->keytab_obtained = (MAX(cred->principal_obtained, cred->username_obtained)); talloc_steal(cred, ktc); cred->keytab = ktc; *_ktc = cred->keytab; talloc_free(mem_ctx); return ret; }
_PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred, struct loadparm_context *lp_ctx, const char *keytab_name, enum credentials_obtained obtained) { krb5_error_code ret; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; TALLOC_CTX *mem_ctx; if (cred->keytab_obtained >= obtained) { return 0; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); if (ret) { return ret; } mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context, NULL, keytab_name, &ktc); if (ret) { return ret; } cred->keytab_obtained = obtained; talloc_steal(cred, ktc); cred->keytab = ktc; talloc_free(mem_ctx); return ret; }
_PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct gssapi_creds_container **_gcc) { int ret = 0; OM_uint32 maj_stat, min_stat; struct gssapi_creds_container *gcc; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; TALLOC_CTX *mem_ctx; krb5_principal princ; const char *error_string; enum credentials_obtained obtained; mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); if (ret) { return ret; } ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ, &obtained, &error_string); if (ret) { DEBUG(1,("cli_credentials_get_server_gss_creds: making krb5 principal failed (%s)\n", error_string)); talloc_free(mem_ctx); return ret; } if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, obtained))) { talloc_free(mem_ctx); *_gcc = cred->server_gss_creds; return 0; } ret = cli_credentials_get_keytab(cred, lp_ctx, &ktc); if (ret) { DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret))); return ret; } gcc = talloc(cred, struct gssapi_creds_container); if (!gcc) { talloc_free(mem_ctx); return ENOMEM; } if (ktc->password_based || obtained < CRED_SPECIFIED) { /* This creates a GSSAPI cred_id_t for match-by-key with only the keytab set */ maj_stat = gss_krb5_import_cred(&min_stat, NULL, NULL, ktc->keytab, &gcc->creds); } else { /* This creates a GSSAPI cred_id_t with the principal and keytab set, matching by name */ maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab, &gcc->creds); } if (maj_stat) { if (min_stat) { ret = min_stat; } else { ret = EINVAL; } } if (ret == 0) { cred->server_gss_creds_obtained = cred->keytab_obtained; talloc_set_destructor(gcc, free_gssapi_creds); cred->server_gss_creds = gcc; *_gcc = gcc; } talloc_free(mem_ctx); return ret; }
/* Get the keytab (actually, a container containing the krb5_keytab) * attached to this context. If this hasn't been done or set before, * it will be generated from the password. */ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct keytab_container **_ktc) { krb5_error_code ret; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; const char *keytab_name; krb5_keytab keytab; TALLOC_CTX *mem_ctx; if (cred->keytab_obtained >= (MAX(cred->principal_obtained, cred->username_obtained))) { *_ktc = cred->keytab; return 0; } if (cli_credentials_is_anonymous(cred)) { return EINVAL; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); if (ret) { return ret; } mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = smb_krb5_create_memory_keytab(mem_ctx, smb_krb5_context->krb5_context, cli_credentials_get_password(cred), cli_credentials_get_username(cred), cli_credentials_get_realm(cred), cli_credentials_get_kvno(cred), &keytab, &keytab_name); if (ret) { talloc_free(mem_ctx); return ret; } ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context, keytab, keytab_name, &ktc); if (ret) { talloc_free(mem_ctx); return ret; } cred->keytab_obtained = (MAX(cred->principal_obtained, cred->username_obtained)); /* We make this keytab up based on a password. Therefore * match-by-key is acceptable, we can't match on the wrong * principal */ ktc->password_based = true; talloc_steal(cred, ktc); cred->keytab = ktc; *_ktc = cred->keytab; talloc_free(mem_ctx); return ret; }
static int cli_credentials_new_ccache(struct cli_credentials *cred, struct loadparm_context *lp_ctx, char *ccache_name, struct ccache_container **_ccc, const char **error_string) { bool must_free_cc_name = false; krb5_error_code ret; struct ccache_container *ccc = talloc(cred, struct ccache_container); if (!ccc) { return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); (*error_string) = talloc_asprintf(cred, "Failed to get krb5_context: %s", error_message(ret)); return ret; } if (!talloc_reference(ccc, ccc->smb_krb5_context)) { talloc_free(ccc); (*error_string) = strerror(ENOMEM); return ENOMEM; } if (!ccache_name) { must_free_cc_name = true; if (lpcfg_parm_bool(lp_ctx, NULL, "credentials", "krb5_cc_file", false)) { ccache_name = talloc_asprintf(ccc, "FILE:/tmp/krb5_cc_samba_%u_%p", (unsigned int)getpid(), ccc); } else { ccache_name = talloc_asprintf(ccc, "MEMORY:%p", ccc); } if (!ccache_name) { talloc_free(ccc); (*error_string) = strerror(ENOMEM); return ENOMEM; } } ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to resolve a krb5 ccache (%s): %s\n", ccache_name, smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)); talloc_free(ccache_name); talloc_free(ccc); return ret; } if (strncasecmp(ccache_name, "MEMORY:", 7) == 0) { talloc_set_destructor(ccc, free_mccache); } else { talloc_set_destructor(ccc, free_dccache); } if (must_free_cc_name) { talloc_free(ccache_name); } *_ccc = ccc; return 0; }
_PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, struct loadparm_context *lp_ctx, const char *name, enum credentials_obtained obtained, const char **error_string) { krb5_error_code ret; krb5_principal princ; struct ccache_container *ccc; if (cred->ccache_obtained > obtained) { return 0; } ccc = talloc(cred, struct ccache_container); if (!ccc) { (*error_string) = error_message(ENOMEM); return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &ccc->smb_krb5_context); if (ret) { (*error_string) = error_message(ret); talloc_free(ccc); return ret; } if (!talloc_reference(ccc, ccc->smb_krb5_context)) { talloc_free(ccc); (*error_string) = error_message(ENOMEM); return ENOMEM; } if (name) { ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to read krb5 ccache: %s: %s\n", name, smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)); talloc_free(ccc); return ret; } } else { ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to read default krb5 ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)); talloc_free(ccc); return ret; } } talloc_set_destructor(ccc, free_dccache); ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); if (ret == 0) { krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ); ret = cli_credentials_set_from_ccache(cred, ccc, obtained, error_string); if (ret) { (*error_string) = error_message(ret); return ret; } cred->ccache = ccc; cred->ccache_obtained = obtained; talloc_steal(cred, ccc); cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained); return 0; } return 0; }
int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, struct gssapi_creds_container **_gcc) { int ret = 0; OM_uint32 maj_stat, min_stat; struct gssapi_creds_container *gcc; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; TALLOC_CTX *mem_ctx; krb5_principal princ; if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, MAX(cred->principal_obtained, cred->username_obtained)))) { *_gcc = cred->server_gss_creds; return 0; } ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context); if (ret) { return ret; } ret = cli_credentials_get_keytab(cred, &ktc); if (ret) { DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret))); return ret; } mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ); if (ret) { DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n", smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return ret; } gcc = talloc(cred, struct gssapi_creds_container); if (!gcc) { talloc_free(mem_ctx); return ENOMEM; } /* This creates a GSSAPI cred_id_t with the principal and keytab set */ maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab, &gcc->creds); if (maj_stat) { if (min_stat) { ret = min_stat; } else { ret = EINVAL; } } if (ret == 0) { cred->server_gss_creds_obtained = cred->keytab_obtained; talloc_set_destructor(gcc, free_gssapi_creds); cred->server_gss_creds = gcc; *_gcc = gcc; } talloc_free(mem_ctx); return ret; }
int cli_credentials_set_ccache(struct cli_credentials *cred, const char *name, enum credentials_obtained obtained) { krb5_error_code ret; krb5_principal princ; struct ccache_container *ccc; if (cred->ccache_obtained > obtained) { return 0; } ccc = talloc(cred, struct ccache_container); if (!ccc) { return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); return ret; } talloc_reference(ccc, ccc->smb_krb5_context); if (name) { ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); if (ret) { DEBUG(1,("failed to read krb5 ccache: %s: %s\n", name, smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccc); return ret; } } else { ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); if (ret) { DEBUG(3,("failed to read default krb5 ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccc); return ret; } } talloc_set_destructor(ccc, free_dccache); ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); if (ret) { DEBUG(3,("failed to get principal from default ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccc); return ret; } krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ); cred->ccache = ccc; talloc_steal(cred, ccc); ret = cli_credentials_set_from_ccache(cred, obtained); if (ret) { return ret; } return 0; }
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi) { krb5_error_code ret; struct gensec_krb5_state *gensec_krb5_state; struct cli_credentials *creds; const struct tsocket_address *tlocal_addr, *tremote_addr; krb5_address my_krb5_addr, peer_krb5_addr; creds = gensec_get_credentials(gensec_security); if (!creds) { return NT_STATUS_INVALID_PARAMETER; } gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state); if (!gensec_krb5_state) { return NT_STATUS_NO_MEMORY; } gensec_security->private_data = gensec_krb5_state; gensec_krb5_state->smb_krb5_context = NULL; gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ticket = NULL; ZERO_STRUCT(gensec_krb5_state->enc_ticket); gensec_krb5_state->keyblock = NULL; gensec_krb5_state->gssapi = gssapi; talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); if (cli_credentials_get_krb5_context(creds, gensec_security->settings->lp_ctx, &gensec_krb5_state->smb_krb5_context)) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } tlocal_addr = gensec_get_local_address(gensec_security); if (tlocal_addr) { ssize_t socklen; struct sockaddr_storage ss; socklen = tsocket_address_bsd_sockaddr(tlocal_addr, (struct sockaddr *) &ss, sizeof(struct sockaddr_storage)); if (socklen < 0) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, (const struct sockaddr *) &ss, &my_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } tremote_addr = gensec_get_remote_address(gensec_security); if (tremote_addr) { ssize_t socklen; struct sockaddr_storage ss; socklen = tsocket_address_bsd_sockaddr(tremote_addr, (struct sockaddr *) &ss, sizeof(struct sockaddr_storage)); if (socklen < 0) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, (const struct sockaddr *) &ss, &peer_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, tlocal_addr ? &my_krb5_addr : NULL, tremote_addr ? &peer_krb5_addr : NULL); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } return NT_STATUS_OK; }
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi) { krb5_error_code ret; struct gensec_krb5_state *gensec_krb5_state; struct cli_credentials *creds; const struct socket_address *my_addr, *peer_addr; krb5_address my_krb5_addr, peer_krb5_addr; creds = gensec_get_credentials(gensec_security); if (!creds) { return NT_STATUS_INVALID_PARAMETER; } gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state); if (!gensec_krb5_state) { return NT_STATUS_NO_MEMORY; } gensec_security->private_data = gensec_krb5_state; gensec_krb5_state->smb_krb5_context = NULL; gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ticket = NULL; ZERO_STRUCT(gensec_krb5_state->enc_ticket); gensec_krb5_state->keyblock = NULL; gensec_krb5_state->session_key = data_blob(NULL, 0); gensec_krb5_state->pac = data_blob(NULL, 0); gensec_krb5_state->gssapi = gssapi; talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); if (cli_credentials_get_krb5_context(creds, gensec_security->event_ctx, gensec_security->settings->lp_ctx, &gensec_krb5_state->smb_krb5_context)) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } my_addr = gensec_get_my_addr(gensec_security); if (my_addr && my_addr->sockaddr) { ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, my_addr->sockaddr, &my_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } peer_addr = gensec_get_peer_addr(gensec_security); if (peer_addr && peer_addr->sockaddr) { ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, peer_addr->sockaddr, &peer_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, my_addr ? &my_krb5_addr : NULL, peer_addr ? &peer_krb5_addr : NULL); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } return NT_STATUS_OK; }
/* Get the keytab (actually, a container containing the krb5_keytab) * attached to this context. If this hasn't been done or set before, * it will be generated from the password. */ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct keytab_container **_ktc) { krb5_error_code ret; struct keytab_container *ktc; struct smb_krb5_context *smb_krb5_context; const char *keytab_name; krb5_keytab keytab; TALLOC_CTX *mem_ctx; const char *username = cli_credentials_get_username(cred); const char *realm = cli_credentials_get_realm(cred); const char *error_string; const char *salt_principal; if (cred->keytab_obtained >= (MAX(cred->principal_obtained, cred->username_obtained))) { *_ktc = cred->keytab; return 0; } if (cli_credentials_is_anonymous(cred)) { return EINVAL; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); if (ret) { return ret; } mem_ctx = talloc_new(cred); if (!mem_ctx) { return ENOMEM; } /* * FIXME: Currently there is no better way than to create the correct * salt principal by checking if the username ends with a '$'. It would * be better if it is part of the credentials. */ ret = smb_krb5_create_salt_principal(mem_ctx, username, realm, &salt_principal, &error_string); if (ret) { talloc_free(mem_ctx); return ret; } ret = smb_krb5_create_memory_keytab(mem_ctx, smb_krb5_context->krb5_context, cli_credentials_get_password(cred), username, realm, salt_principal, cli_credentials_get_kvno(cred), &keytab, &keytab_name); if (ret) { talloc_free(mem_ctx); return ret; } ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context, keytab, keytab_name, &ktc); if (ret) { talloc_free(mem_ctx); return ret; } cred->keytab_obtained = (MAX(cred->principal_obtained, cred->username_obtained)); /* We make this keytab up based on a password. Therefore * match-by-key is acceptable, we can't match on the wrong * principal */ ktc->password_based = true; talloc_steal(cred, ktc); cred->keytab = ktc; *_ktc = cred->keytab; talloc_free(mem_ctx); return ret; }