From 83a16a65b5c1bb8435505fe7f3b0cc805048821c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 8 Aug 2014 09:47:19 -0400 Subject: Improve role management A server can be standalone or domain member, improve role management so we can autodetct which role we should assume as a server. --- src/gss_ntlmssp.c | 37 +++++++++++++++++++++++++++++++++---- src/gss_ntlmssp.h | 9 +++++++-- src/gss_sec_ctx.c | 20 +++++++++----------- 3 files changed, 49 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/gss_ntlmssp.c b/src/gss_ntlmssp.c index e4a6336..666508b 100644 --- a/src/gss_ntlmssp.c +++ b/src/gss_ntlmssp.c @@ -28,8 +28,7 @@ const gss_OID_desc gssntlm_oid = { .elements = discard_const(GSS_NTLMSSP_OID_STRING) }; -uint8_t gssntlm_required_security(int security_level, - enum gssntlm_role role) +uint8_t gssntlm_required_security(int security_level, struct gssntlm_ctx *ctx) { uint8_t resp; @@ -51,10 +50,10 @@ uint8_t gssntlm_required_security(int security_level, break; case 4: resp |= SEC_NTLM_OK | SEC_EXT_SEC_OK; - if (role == GSSNTLM_DOMAIN_CONTROLLER) resp &= ~SEC_DC_LM_OK; + if (ctx->role == GSSNTLM_DOMAIN_CONTROLLER) resp &= ~SEC_DC_LM_OK; break; case 5: - if (role == GSSNTLM_DOMAIN_CONTROLLER) resp = SEC_DC_V2_OK; + if (ctx->role == GSSNTLM_DOMAIN_CONTROLLER) resp = SEC_DC_V2_OK; resp |= SEC_V2_ONLY | SEC_EXT_SEC_OK; break; default: @@ -65,6 +64,36 @@ uint8_t gssntlm_required_security(int security_level, return resp; } +void gssntlm_set_role(struct gssntlm_ctx *ctx, + int desired, char *nb_domain_name) +{ + if (desired == GSSNTLM_CLIENT) { + ctx->role = GSSNTLM_CLIENT; + } else if (nb_domain_name && *nb_domain_name) { + ctx->role = GSSNTLM_DOMAIN_SERVER; + } else { + ctx->role = GSSNTLM_SERVER; + } +} + +bool gssntlm_role_is_client(struct gssntlm_ctx *ctx) +{ + return (ctx->role == GSSNTLM_CLIENT); +} + +bool gssntlm_role_is_server(struct gssntlm_ctx *ctx) +{ + switch (ctx->role) { + case GSSNTLM_SERVER: + case GSSNTLM_DOMAIN_SERVER: + case GSSNTLM_DOMAIN_CONTROLLER: + return true; + default: + break; + } + return false; +} + bool gssntlm_sec_lm_ok(struct gssntlm_ctx *ctx) { switch (ctx->role) { diff --git a/src/gss_ntlmssp.h b/src/gss_ntlmssp.h index efae6c7..5777968 100644 --- a/src/gss_ntlmssp.h +++ b/src/gss_ntlmssp.h @@ -154,8 +154,13 @@ struct gssntlm_ctx { time_t expiration_time; }; -uint8_t gssntlm_required_security(int security_level, - enum gssntlm_role role); +uint8_t gssntlm_required_security(int security_level, struct gssntlm_ctx *ctx); + +void gssntlm_set_role(struct gssntlm_ctx *ctx, + int desired, char *nb_domain_name); +bool gssntlm_role_is_client(struct gssntlm_ctx *ctx); +bool gssntlm_role_is_server(struct gssntlm_ctx *ctx); + bool gssntlm_sec_lm_ok(struct gssntlm_ctx *ctx); bool gssntlm_sec_ntlm_ok(struct gssntlm_ctx *ctx); bool gssntlm_ext_sec_ok(struct gssntlm_ctx *ctx); diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c index 40817b8..4802567 100644 --- a/src/gss_sec_ctx.c +++ b/src/gss_sec_ctx.c @@ -127,8 +127,6 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, ctx->gss_flags = req_flags; - ctx->role = GSSNTLM_CLIENT; - ctx->neg_flags = NTLMSSP_DEFAULT_CLIENT_FLAGS; /* @@ -204,10 +202,12 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, goto done; } + gssntlm_set_role(ctx, GSSNTLM_CLIENT, nb_domain_name); + ctx->neg_flags |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED; lm_compat_lvl = gssntlm_get_lm_compatibility_level(); - ctx->sec_req = gssntlm_required_security(lm_compat_lvl, ctx->role); + ctx->sec_req = gssntlm_required_security(lm_compat_lvl, ctx); if (ctx->sec_req == 0xff) { retmaj = GSS_S_FAILURE; goto done; @@ -285,7 +285,7 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, } else { - if (ctx->role != GSSNTLM_CLIENT) { + if (!gssntlm_role_is_client(ctx)) { retmaj = GSS_S_NO_CONTEXT; goto done; } @@ -631,13 +631,10 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, goto done; } - /* FIXME: add call to determine if we are any other type of - * server, including setting up callbacks to perform validation - * against a remote DC */ - ctx->role = GSSNTLM_SERVER; + gssntlm_set_role(ctx, GSSNTLM_SERVER, nb_domain_name); lm_compat_lvl = gssntlm_get_lm_compatibility_level(); - ctx->sec_req = gssntlm_required_security(lm_compat_lvl, ctx->role); + ctx->sec_req = gssntlm_required_security(lm_compat_lvl, ctx); if (ctx->sec_req == 0xff) { retmaj = GSS_S_FAILURE; goto done; @@ -779,7 +776,8 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, } else { ctx = (struct gssntlm_ctx *)(*context_handle); - if (ctx->role != GSSNTLM_SERVER) { + if (!gssntlm_role_is_server(ctx)) { + retmin = EINVAL; retmaj = GSS_S_NO_CONTEXT; goto done; } @@ -1060,7 +1058,7 @@ uint32_t gssntlm_inquire_context(uint32_t *minor_status, } if (locally_initiated) { - if (ctx->role == GSSNTLM_CLIENT) { + if (gssntlm_role_is_client(ctx)) { *locally_initiated = 1; } else { *locally_initiated = 0; -- cgit