diff options
-rw-r--r-- | src/external.c | 5 | ||||
-rw-r--r-- | src/gss_names.c | 78 | ||||
-rw-r--r-- | src/gss_ntlmssp.h | 5 | ||||
-rw-r--r-- | src/gss_sec_ctx.c | 91 |
4 files changed, 125 insertions, 54 deletions
diff --git a/src/external.c b/src/external.c index 11dcec8..07bbaab 100644 --- a/src/external.c +++ b/src/external.c @@ -3,6 +3,11 @@ #include <errno.h> #include "gss_ntlmssp.h" +uint32_t external_netbios_get_names(char **computer, char **domain) +{ + return ENOSYS; +} + uint32_t external_get_creds(struct gssntlm_name *name, struct gssntlm_cred *cred) { diff --git a/src/gss_names.c b/src/gss_names.c index f48d117..e25c707 100644 --- a/src/gss_names.c +++ b/src/gss_names.c @@ -17,6 +17,7 @@ #define _GNU_SOURCE +#include <ctype.h> #include <errno.h> #include <limits.h> #include <pwd.h> @@ -529,3 +530,80 @@ done: localname->length = strlen(uname) + 1; return GSS_S_COMPLETE; } + +uint32_t netbios_get_names(char *computer_name, + char **netbios_host, char **netbios_domain) +{ + char *nb_computer_name = NULL; + char *nb_domain_name = NULL; + char *env_name; + uint32_t ret; + + env_name = getenv("NETBIOS_COMPUTER_NAME"); + if (env_name) { + nb_computer_name = strdup(env_name); + if (!nb_computer_name) { + ret = ENOMEM; + goto done; + } + } + + env_name = getenv("NETBIOS_DOMAIN_NAME"); + if (env_name) { + nb_domain_name = strdup(env_name); + if (!nb_domain_name) { + ret = ENOMEM; + goto done; + } + } + + if (!nb_computer_name || !nb_domain_name) { + /* fetch only missing ones */ + ret = external_netbios_get_names( + nb_computer_name ? NULL : &nb_computer_name, + nb_domain_name ? NULL : &nb_domain_name); + if ((ret != 0) && + (ret != ENOENT) && + (ret != ENOSYS)) { + goto done; + } + } + + if (!nb_computer_name) { + char *p; + p = strchr(computer_name, '.'); + if (p) { + nb_computer_name = strndup(computer_name, p - computer_name); + } else { + nb_computer_name = strdup(computer_name); + } + for (p = nb_computer_name; p && *p; p++) { + /* Can only be ASCII, so toupper is safe */ + *p = toupper(*p); + } + if (!nb_computer_name) { + ret = ENOMEM; + goto done; + } + } + + if (!nb_domain_name) { + nb_domain_name = strdup("WORKGROUP"); + if (!nb_domain_name) { + ret = ENOMEM; + goto done; + } + } + + ret = 0; + +done: + if (ret) { + safefree(nb_computer_name); + safefree(nb_domain_name); + } + + *netbios_domain = nb_domain_name; + *netbios_host = nb_computer_name; + return ret; +} diff --git a/src/gss_ntlmssp.h b/src/gss_ntlmssp.h index 887138f..7d45d41 100644 --- a/src/gss_ntlmssp.h +++ b/src/gss_ntlmssp.h @@ -168,7 +168,7 @@ void gssntlm_int_release_cred(struct gssntlm_cred *cred); int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst); int gssntlm_copy_creds(struct gssntlm_cred *in, struct gssntlm_cred *out); - +uint32_t external_netbios_get_names(char **computer, char **domain); uint32_t external_get_creds(struct gssntlm_name *name, struct gssntlm_cred *cred); uint32_t external_srv_auth(char *user, char *domain, @@ -177,6 +177,9 @@ uint32_t external_srv_auth(char *user, char *domain, struct ntlm_buffer *lm_chal_resp, struct ntlm_key *ntlmv2_key); +uint32_t netbios_get_names(char *computer_name, + char **netbios_host, char **netbios_domain); + uint32_t gssntlm_srv_auth(uint32_t *minor, struct gssntlm_ctx *ctx, struct gssntlm_cred *cred, diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c index 89972e6..265d24e 100644 --- a/src/gss_sec_ctx.c +++ b/src/gss_sec_ctx.c @@ -15,7 +15,6 @@ License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include <ctype.h> #include <errno.h> #include <stdlib.h> #include <string.h> @@ -41,8 +40,10 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, struct gssntlm_ctx *ctx; struct gssntlm_name *server = NULL; struct gssntlm_cred *cred = NULL; - char *env_name; - char *workstation = NULL; + char *computer_name = NULL; + char *nb_computer_name = NULL; + char *nb_domain_name = NULL; + struct gssntlm_name *client_name = NULL; const char *domain = NULL; uint32_t in_flags; uint32_t msg_type; @@ -185,40 +186,41 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, domain = cred->cred.user.user.data.user.domain; } - env_name = getenv("NETBIOS_COMPUTER_NAME"); - if (env_name) { - workstation = strdup(env_name); - } else { /* acquire our own name */ - gss_buffer_desc tmpbuf = { 0, discard_const("") }; - struct gssntlm_name *tmpname; - char *p; + if (!client_name) { + gss_buffer_desc tmpbuf; + tmpbuf.value = discard_const(""); + tmpbuf.length = 0; retmaj = gssntlm_import_name_by_mech(&retmin, &gssntlm_oid, &tmpbuf, GSS_C_NT_HOSTBASED_SERVICE, - (gss_name_t *)&tmpname); + (gss_name_t *)&client_name); if (retmaj) goto done; - p = strchr(tmpname->data.server.name, '.'); - if (p) { - workstation = strndup(tmpname->data.server.name, - p - tmpname->data.server.name); - } else { - workstation = strdup(tmpname->data.server.name); - } - for (p = workstation; p && *p; p++) { - /* Can only be ASCII, so toupper is safe */ - *p = toupper(*p); - } - gssntlm_release_name(&tmpmin, (gss_name_t *)&tmpname); } - if (!workstation) { + + computer_name = strdup(client_name->data.server.name); + if (!computer_name) { retmin = ENOMEM; retmaj = GSS_S_FAILURE; goto done; } + + retmin = netbios_get_names(computer_name, + &nb_computer_name, &nb_domain_name); + if (retmin) { + retmaj = GSS_S_FAILURE; + goto done; + } + + ctx->workstation = strdup(nb_computer_name); + if (!ctx->workstation) { + retmin = ENOMEM; + retmaj = GSS_S_FAILURE; + goto done; + } + ctx->neg_flags |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED; - ctx->workstation = workstation; lm_compat_lvl = gssntlm_get_lm_compatibility_level(); sec_req = gssntlm_required_security(lm_compat_lvl, ctx->role); @@ -266,7 +268,7 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, } retmin = ntlm_encode_neg_msg(ctx->ntlm, ctx->neg_flags, - domain, workstation, &ctx->nego_msg); + domain, ctx->workstation, &ctx->nego_msg); if (retmin) { retmaj = GSS_S_FAILURE; goto done; @@ -694,6 +696,10 @@ done: /* do not leak it, if not passed in */ gssntlm_release_cred(&tmpmin, (gss_cred_id_t *)&cred); } + gssntlm_release_name(&tmpmin, (gss_name_t *)&client_name); + safefree(computer_name); + safefree(nb_computer_name); + safefree(nb_domain_name); safefree(trgt_name); ntlm_free_buffer_data(&client_target_info); ntlm_free_buffer_data(&target_info); @@ -787,9 +793,7 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, char *computer_name = NULL; char *nb_computer_name = NULL; char *nb_domain_name = NULL; - char *env_name; char *chal_target_name; - gss_buffer_desc tmpbuf; uint64_t timestamp; struct ntlm_buffer target_info = { 0 }; struct ntlm_buffer nt_chal_resp = { 0 }; @@ -813,7 +817,6 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, struct ntlm_buffer unhashed_cb = { 0 }; struct ntlm_buffer av_cb = { 0 }; uint8_t sec_req; - char *p; if (context_handle == NULL) return GSS_S_CALL_INACCESSIBLE_READ; if (output_token == GSS_C_NO_BUFFER) { @@ -963,6 +966,7 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, /* acquire our own name */ if (!server_name) { + gss_buffer_desc tmpbuf; tmpbuf.value = discard_const(""); tmpbuf.length = 0; retmaj = gssntlm_import_name_by_mech(&retmin, @@ -986,34 +990,15 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, goto done; } - env_name = getenv("NETBIOS_COMPUTER_NAME"); - if (env_name) { - nb_computer_name = strdup(env_name); - } else { - p = strchr(computer_name, '.'); - if (p) { - nb_computer_name = strndup(computer_name, p - computer_name); - } else { - nb_computer_name = strdup(computer_name); - } - for (p = nb_computer_name; p && *p; p++) { - /* Can only be ASCII, so toupper is safe */ - *p = toupper(*p); - } - } - if (!nb_computer_name) { - retmin = ENOMEM; + retmin = netbios_get_names(computer_name, + &nb_computer_name, &nb_domain_name); + if (retmin) { retmaj = GSS_S_FAILURE; goto done; } - env_name = getenv("NETBIOS_DOMAIN_NAME"); - if (env_name) { - nb_domain_name = strdup(env_name); - } else { - nb_domain_name = strdup("WORKGROUP"); - } - if (!nb_domain_name) { + ctx->workstation = strdup(nb_computer_name); + if (!ctx->workstation) { retmin = ENOMEM; retmaj = GSS_S_FAILURE; goto done; |