summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-05-15 13:59:09 +0200
committerSimo Sorce <simo@redhat.com>2014-08-07 12:44:46 -0400
commit606a92c567e11565215d80e7e1424092c8eb0bde (patch)
treea3dcbe7e904ddef0fff745f576071f061d7b8f51
parent9900ca295bb598eede3222a60ce5b9b1cf68166e (diff)
downloadgss-ntlmssp-606a92c567e11565215d80e7e1424092c8eb0bde.tar.gz
gss-ntlmssp-606a92c567e11565215d80e7e1424092c8eb0bde.tar.xz
gss-ntlmssp-606a92c567e11565215d80e7e1424092c8eb0bde.zip
Add support to perform external operations
This allows the code to know it has to use an external mechanism, such as winbind, to handle authentication. Based on work from David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--Makefile.am2
-rw-r--r--src/external.c19
-rw-r--r--src/gss_auth.c104
-rw-r--r--src/gss_creds.c17
-rw-r--r--src/gss_ntlmssp.h22
-rw-r--r--src/gss_sec_ctx.c71
-rw-r--r--src/gss_serialize.c13
7 files changed, 188 insertions, 60 deletions
diff --git a/Makefile.am b/Makefile.am
index 169c199..becf2bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,8 @@ GN_MECHGLUE_OBJ = \
src/gss_sec_ctx.c \
src/gss_signseal.c \
src/gss_serialize.c \
+ src/external.c \
+ src/gss_auth.c \
src/gss_ntlmssp.c
dist_noinst_HEADERS = \
diff --git a/src/external.c b/src/external.c
new file mode 100644
index 0000000..11dcec8
--- /dev/null
+++ b/src/external.c
@@ -0,0 +1,19 @@
+/* Copyright (C) 2014 GSS-NTLMSSP contributors, see COPYING for License */
+
+#include <errno.h>
+#include "gss_ntlmssp.h"
+
+uint32_t external_get_creds(struct gssntlm_name *name,
+ struct gssntlm_cred *cred)
+{
+ return ENOSYS;
+}
+
+uint32_t external_srv_auth(char *user, char *domain,
+ char *workstation, uint8_t *challenge,
+ struct ntlm_buffer *nt_chal_resp,
+ struct ntlm_buffer *lm_chal_resp,
+ struct ntlm_key *ntlmv2_key)
+{
+ return ENOSYS;
+}
diff --git a/src/gss_auth.c b/src/gss_auth.c
new file mode 100644
index 0000000..710099f
--- /dev/null
+++ b/src/gss_auth.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2014 GSS-NTLMSSP contributors, see COPYING for License */
+
+#include <errno.h>
+#include "gss_ntlmssp.h"
+
+uint32_t gssntlm_srv_auth(uint32_t *minor,
+ struct gssntlm_ctx *ctx,
+ struct gssntlm_cred *cred,
+ struct ntlm_buffer *nt_chal_resp,
+ struct ntlm_buffer *lm_chal_resp,
+ struct ntlm_key *key_exchange_key)
+{
+ struct ntlm_key ntlmv2_key = { .length = 16 };
+ struct ntlm_buffer nt_proof = { 0 };
+ uint32_t retmaj, retmin;
+ const char *domstr;
+ int retries;
+
+ if (key_exchange_key->length != 16) {
+ *minor = EINVAL;
+ return GSS_S_FAILURE;
+ }
+
+ switch (cred->type) {
+
+ case GSSNTLM_CRED_USER:
+ for (retries = 2; retries > 0; retries--) {
+
+ if (retries == 2) {
+ domstr = cred->cred.user.user.data.user.domain;
+ } else {
+ domstr = NULL;
+ }
+
+ /* NTLMv2 Key */
+ retmin = NTOWFv2(ctx->ntlm, &cred->cred.user.nt_hash,
+ cred->cred.user.user.data.user.name,
+ domstr, &ntlmv2_key);
+ if (retmin) {
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+
+ /* NTLMv2 Response */
+ retmin = ntlmv2_verify_nt_response(nt_chal_resp,
+ &ntlmv2_key,
+ ctx->server_chal);
+ if (retmin == 0) {
+ break;
+ } else {
+ if (ctx->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
+ /* LMv2 Response */
+ retmin = ntlmv2_verify_lm_response(lm_chal_resp,
+ &ntlmv2_key,
+ ctx->server_chal);
+ if (retmin == 0) {
+ break;
+ }
+ }
+ }
+ if (retmin && retries < 2) {
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ }
+ /* The NT proof is the first 16 bytes */
+ nt_proof.data = nt_chal_resp->data;
+ nt_proof.length = 16;
+
+ /* The Session Base Key */
+ /* In NTLMv2 the Key Exchange Key is the Session Base Key */
+ retmin = ntlmv2_session_base_key(&ntlmv2_key, &nt_proof,
+ key_exchange_key);
+ if (retmin) {
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ break;
+
+ case GSSNTLM_CRED_EXTERNAL:
+ retmin = external_srv_auth(cred->cred.external.user.data.user.name,
+ cred->cred.external.user.data.user.domain,
+ ctx->workstation, ctx->server_chal,
+ nt_chal_resp, lm_chal_resp,
+ key_exchange_key);
+ if (retmin) {
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ break;
+
+ default:
+ retmin = EINVAL;
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+
+ retmaj = GSS_S_COMPLETE;
+ retmin = 0;
+
+done:
+ *minor = retmin;
+ return retmaj;
+}
diff --git a/src/gss_creds.c b/src/gss_creds.c
index 17ac3f6..080de5d 100644
--- a/src/gss_creds.c
+++ b/src/gss_creds.c
@@ -273,6 +273,11 @@ int gssntlm_copy_creds(struct gssntlm_cred *in, struct gssntlm_cred *out)
&out->cred.server.name);
if (ret) goto done;
break;
+ case GSSNTLM_CRED_EXTERNAL:
+ ret = gssntlm_copy_name(&in->cred.external.user,
+ &out->cred.external.user);
+ if (ret) goto done;
+ break;
}
out->type = in->type;
@@ -305,6 +310,9 @@ void gssntlm_int_release_cred(struct gssntlm_cred *cred)
case GSSNTLM_CRED_SERVER:
gssntlm_int_release_name(&cred->cred.server.name);
break;
+ case GSSNTLM_CRED_EXTERNAL:
+ gssntlm_int_release_name(&cred->cred.external.user);
+ break;
}
}
@@ -365,6 +373,9 @@ uint32_t gssntlm_acquire_cred_from(uint32_t *minor_status,
retmin = get_creds_from_store(name, cred, cred_store);
} else {
retmin = get_user_file_creds(name, cred);
+ if (retmin) {
+ retmin = external_get_creds(name, cred);
+ }
}
if (retmin) {
retmaj = GSS_S_CRED_UNAVAIL;
@@ -500,6 +511,12 @@ uint32_t gssntlm_inquire_cred(uint32_t *minor_status,
name);
if (maj != GSS_S_COMPLETE) return maj;
break;
+ case GSSNTLM_CRED_EXTERNAL:
+ maj = gssntlm_duplicate_name(minor_status,
+ (gss_name_t)&cred->cred.external.user,
+ name);
+ if (maj != GSS_S_COMPLETE) return maj;
+ break;
}
}
diff --git a/src/gss_ntlmssp.h b/src/gss_ntlmssp.h
index 0b4df0d..887138f 100644
--- a/src/gss_ntlmssp.h
+++ b/src/gss_ntlmssp.h
@@ -89,7 +89,8 @@ struct gssntlm_cred {
GSSNTLM_CRED_NONE,
GSSNTLM_CRED_ANON,
GSSNTLM_CRED_USER,
- GSSNTLM_CRED_SERVER
+ GSSNTLM_CRED_SERVER,
+ GSSNTLM_CRED_EXTERNAL,
} type;
union {
@@ -104,6 +105,9 @@ struct gssntlm_cred {
struct {
struct gssntlm_name name;
} server;
+ struct {
+ struct gssntlm_name user;
+ } external;
} cred;
};
@@ -164,7 +168,21 @@ 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);
-extern const gss_OID_desc gssntlm_oid;
+
+uint32_t external_get_creds(struct gssntlm_name *name,
+ struct gssntlm_cred *cred);
+uint32_t external_srv_auth(char *user, char *domain,
+ char *workstation, uint8_t *challenge,
+ struct ntlm_buffer *nt_chal_resp,
+ struct ntlm_buffer *lm_chal_resp,
+ struct ntlm_key *ntlmv2_key);
+
+uint32_t gssntlm_srv_auth(uint32_t *minor,
+ struct gssntlm_ctx *ctx,
+ struct gssntlm_cred *cred,
+ struct ntlm_buffer *nt_chal_resp,
+ struct ntlm_buffer *lm_chal_resp,
+ struct ntlm_key *key_exchange_key);
extern const gss_OID_desc gssntlm_oid;
diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c
index 12a15c5..8e43033 100644
--- a/src/gss_sec_ctx.c
+++ b/src/gss_sec_ctx.c
@@ -24,7 +24,6 @@
#include "gssapi_ntlmssp.h"
#include "gss_ntlmssp.h"
-
uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
gss_cred_id_t claimant_cred_handle,
gss_ctx_id_t *context_handle,
@@ -1145,16 +1144,15 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
/* FIXME: not supported for now */
retmin = EINVAL;
retmaj = GSS_S_FAILURE;
+ goto done;
+ }
- } else if (sec_req & SEC_V2_ONLY) {
+ if (sec_req & SEC_V2_ONLY) {
/* ### NTLMv2 ### */
- struct ntlm_key ntlmv2_key = { .length = 16 };
- struct ntlm_buffer nt_proof = { 0 };
char useratdom[1024];
size_t ulen, dlen, uadlen;
gss_buffer_desc usrname;
- int retries;
if (!dom_name) {
dom_name = strdup("");
@@ -1197,67 +1195,24 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
(gss_cred_id_t *)&usr_cred,
NULL, NULL);
if (retmaj) goto done;
-
- retmin = gssntlm_copy_name(gss_usrname, &ctx->source_name);
- if (retmin) {
- retmaj = GSS_S_FAILURE;
+ /* We can't handle winbind credentials yet */
+ if (usr_cred->type != GSSNTLM_CRED_USER) {
+ retmin = EINVAL;
+ retmaj = GSS_S_CRED_UNAVAIL;
goto done;
}
- for (retries = 2; retries > 0; retries--) {
- const char *domstr;
-
- if (retries == 2) {
- domstr = usr_cred->cred.user.user.data.user.domain;
- } else {
- domstr = NULL;
- }
-
- /* NTLMv2 Key */
- retmin = NTOWFv2(ctx->ntlm, &usr_cred->cred.user.nt_hash,
- usr_cred->cred.user.user.data.user.name,
- domstr, &ntlmv2_key);
- if (retmin) {
- retmaj = GSS_S_FAILURE;
- goto done;
- }
-
- /* NTLMv2 Response */
- retmin = ntlmv2_verify_nt_response(&nt_chal_resp,
- &ntlmv2_key,
- ctx->server_chal);
- if (retmin == 0) {
- break;
- } else {
- if (ctx->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
- /* LMv2 Response */
- retmin = ntlmv2_verify_lm_response(&lm_chal_resp,
- &ntlmv2_key,
- ctx->server_chal);
- if (retmin == 0) {
- break;
- }
- }
- }
- if (retmin && retries < 2) {
- retmaj = GSS_S_FAILURE;
- goto done;
- }
- }
-
- /* The NT proof is the first 16 bytes */
- nt_proof.data = nt_chal_resp.data;
- nt_proof.length = 16;
-
- /* The Session Base Key */
- /* In NTLMv2 the Key Exchange Key is the Session Base Key */
- retmin = ntlmv2_session_base_key(&ntlmv2_key, &nt_proof,
- &key_exchange_key);
+ retmin = gssntlm_copy_name(gss_usrname, &ctx->source_name);
if (retmin) {
retmaj = GSS_S_FAILURE;
goto done;
}
+ retmaj = gssntlm_srv_auth(&retmin, ctx, usr_cred,
+ &nt_chal_resp, &lm_chal_resp,
+ &key_exchange_key);
+ if (retmaj) goto done;
+
} else {
/* ### NTLMv1 ### */
retmaj = GSS_S_FAILURE;
diff --git a/src/gss_serialize.c b/src/gss_serialize.c
index 4d54ff5..fb26b94 100644
--- a/src/gss_serialize.c
+++ b/src/gss_serialize.c
@@ -749,6 +749,7 @@ struct export_cred {
#define EXP_CRED_ANON 1
#define EXP_CRED_USER 2
#define EXP_CRED_SERVER 3
+#define EXP_CRED_EXTERNAL 4
uint32_t gssntlm_export_cred(uint32_t *minor_status,
gss_cred_id_t cred_handle,
@@ -814,6 +815,12 @@ uint32_t gssntlm_export_cred(uint32_t *minor_status,
ret = export_name(&state, &cred->cred.server.name, &ecred->name);
if (ret) goto done;
break;
+ case GSSNTLM_CRED_EXTERNAL:
+ ecred->type = EXP_CRED_EXTERNAL;
+
+ ret = export_name(&state, &cred->cred.external.user, &ecred->name);
+ if (ret) goto done;
+ break;
}
ret = 0;
@@ -909,6 +916,12 @@ uint32_t gssntlm_import_cred(uint32_t *minor_status,
&cred->cred.server.name);
if (maj != GSS_S_COMPLETE) goto done;
break;
+ case EXP_CRED_EXTERNAL:
+ cred->type = GSSNTLM_CRED_EXTERNAL;
+ maj = import_name(minor_status, &state, &ecred->name,
+ &cred->cred.external.user);
+ if (maj != GSS_S_COMPLETE) goto done;
+ break;
default:
maj = GSS_S_DEFECTIVE_TOKEN;
break;