summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/external.c5
-rw-r--r--src/gss_names.c78
-rw-r--r--src/gss_ntlmssp.h5
-rw-r--r--src/gss_sec_ctx.c91
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;