summaryrefslogtreecommitdiff
path: root/source3/librpc/crypto/gse.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/librpc/crypto/gse.c')
-rw-r--r--source3/librpc/crypto/gse.c93
1 files changed, 68 insertions, 25 deletions
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index a111320e829..cc62849b7b2 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -120,6 +120,54 @@ static int gse_context_destructor(void *ptr)
return 0;
}
+static NTSTATUS gse_setup_server_principal(TALLOC_CTX *mem_ctx,
+ const char *target_principal,
+ const char *service,
+ const char *hostname,
+ const char *realm,
+ char **pserver_principal,
+ gss_name_t *pserver_name)
+{
+ char *server_principal = NULL;
+ gss_buffer_desc name_token;
+ gss_OID name_type;
+ OM_uint32 maj_stat, min_stat = 0;
+
+ if (target_principal != NULL) {
+ server_principal = talloc_strdup(mem_ctx, target_principal);
+ name_type = GSS_C_NULL_OID;
+ } else {
+ server_principal = talloc_asprintf(mem_ctx,
+ "%s/%s@%s",
+ service,
+ hostname,
+ realm);
+ name_type = GSS_C_NT_USER_NAME;
+ }
+ if (server_principal == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ name_token.value = (uint8_t *)server_principal;
+ name_token.length = strlen(server_principal);
+
+ maj_stat = gss_import_name(&min_stat,
+ &name_token,
+ name_type,
+ pserver_name);
+ if (maj_stat) {
+ DBG_WARNING("GSS Import name of %s failed: %s\n",
+ server_principal,
+ gse_errstr(mem_ctx, maj_stat, min_stat));
+ TALLOC_FREE(server_principal);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ *pserver_principal = server_principal;
+
+ return NT_STATUS_OK;
+}
+
static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
bool do_sign, bool do_seal,
const char *ccache_name,
@@ -203,11 +251,12 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
{
struct gse_context *gse_ctx;
OM_uint32 gss_maj, gss_min;
- gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER;
#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
gss_OID oid = discard_const(GSS_KRB5_CRED_NO_CI_FLAGS_X);
#endif
+ char *server_principal = NULL;
+ char *server_realm = NULL;
NTSTATUS status;
if (!server || !service) {
@@ -223,30 +272,24 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
/* Guess the realm based on the supplied service, and avoid the GSS libs
doing DNS lookups which may fail.
-
- TODO: Loop with the KDC on some more combinations (local
- realm in particular), possibly falling back to
- GSS_C_NT_HOSTBASED_SERVICE
*/
- name_buffer.value =
- smb_krb5_get_principal_from_service_hostname(gse_ctx,
- service,
- server,
- realm);
- if (!name_buffer.value) {
- status = NT_STATUS_NO_MEMORY;
- goto err_out;
+ server_realm = smb_krb5_get_realm_from_hostname(mem_ctx,
+ server,
+ realm);
+ if (server_realm == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- name_buffer.length = strlen((char *)name_buffer.value);
- gss_maj = gss_import_name(&gss_min, &name_buffer,
- GSS_C_NT_USER_NAME,
- &gse_ctx->server_name);
- if (gss_maj) {
- DEBUG(5, ("gss_import_name failed for %s, with [%s]\n",
- (char *)name_buffer.value,
- gse_errstr(gse_ctx, gss_maj, gss_min)));
- status = NT_STATUS_INTERNAL_ERROR;
- goto err_out;
+
+ status = gse_setup_server_principal(mem_ctx,
+ NULL,
+ service,
+ server,
+ server_realm,
+ &server_principal,
+ &gse_ctx->server_name);
+ TALLOC_FREE(server_realm);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* TODO: get krb5 ticket using username/password, if no valid
@@ -300,11 +343,11 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
#endif
*_gse_ctx = gse_ctx;
- TALLOC_FREE(name_buffer.value);
+ TALLOC_FREE(server_principal);
return NT_STATUS_OK;
err_out:
- TALLOC_FREE(name_buffer.value);
+ TALLOC_FREE(server_principal);
TALLOC_FREE(gse_ctx);
return status;
}