summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-01-12 16:38:05 -0500
committerSimo Sorce <simo@redhat.com>2014-01-12 18:28:02 -0500
commit3bbd2d913d30a7f19a4dec752e00047584d0beab (patch)
tree0e738eb63028d4d06dfe45305756477cb0fa5e9a
parent60feddb149ed12ea922a53f67768f3385de50393 (diff)
downloadgss-ntlmssp-export_cred.tar.gz
gss-ntlmssp-export_cred.tar.xz
gss-ntlmssp-export_cred.zip
Implement Import/Export cred functionsexport_cred
-rw-r--r--src/gss_ntlmssp.h8
-rw-r--r--src/gss_serialize.c194
-rw-r--r--src/gss_spi.c14
3 files changed, 216 insertions, 0 deletions
diff --git a/src/gss_ntlmssp.h b/src/gss_ntlmssp.h
index 89da78d..c25cb52 100644
--- a/src/gss_ntlmssp.h
+++ b/src/gss_ntlmssp.h
@@ -326,4 +326,12 @@ uint32_t gssntlm_export_sec_context(uint32_t *minor_status,
uint32_t gssntlm_import_sec_context(uint32_t *minor_status,
gss_buffer_t interprocess_token,
gss_ctx_id_t *context_handle);
+
+uint32_t gssntlm_export_cred(uint32_t *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_buffer_t token);
+
+uint32_t gssntlm_import_cred(uint32_t *minor_status,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle);
#endif /* _GSS_NTLMSSP_H_ */
diff --git a/src/gss_serialize.c b/src/gss_serialize.c
index 03639ad..9ea02f4 100644
--- a/src/gss_serialize.c
+++ b/src/gss_serialize.c
@@ -723,3 +723,197 @@ done:
}
return maj;
}
+
+#pragma pack(push, 1)
+struct export_cred {
+ uint16_t version; /* 0x00 0x01 */
+ uint16_t type;
+
+ struct export_name name; /* user or server name */
+ struct relmem nt_hash; /* empty for dummy or server */
+ struct relmem lm_hash; /* empty for dummy or server */
+
+ uint8_t data[];
+};
+#pragma pack(pop)
+
+#define EXP_CRED_NONE 0
+#define EXP_CRED_ANON 1
+#define EXP_CRED_USER 2
+#define EXP_CRED_SERVER 3
+
+uint32_t gssntlm_export_cred(uint32_t *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_buffer_t token)
+{
+ struct gssntlm_cred *cred;
+ struct export_state state;
+ struct export_cred *ecred;
+ int ret;
+
+ if (token == NULL || minor_status == NULL) {
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+ }
+
+ *minor_status = 0;
+
+ cred = (struct gssntlm_cred *)cred_handle;
+ if (cred_handle == NULL) {
+ return GSS_S_NO_CRED;
+ }
+
+ state.exp_size = NEW_SIZE(0, sizeof(struct export_cred));
+ state.exp_struct = calloc(1, state.exp_size);
+ if (!state.exp_struct) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ ecred = (struct export_cred *)state.exp_struct;
+ state.exp_data = (void *)ecred->data - (void *)ecred;
+ state.exp_len = state.exp_data;
+ state.exp_ptr = 0;
+
+ ecred->version = htole16(1);
+
+ switch (cred->type) {
+ case GSSNTLM_CRED_NONE:
+ ecred->type = EXP_CRED_NONE;
+ break;
+ case GSSNTLM_CRED_ANON:
+ ecred->type = EXP_CRED_ANON;
+ break;
+ case GSSNTLM_CRED_USER:
+ ecred->type = EXP_CRED_USER;
+
+ ret = export_name(&state, &cred->cred.user.user, &ecred->name);
+ if (ret) goto done;
+
+ ret = export_data_buffer(&state,
+ cred->cred.user.nt_hash.data,
+ cred->cred.user.nt_hash.length,
+ &ecred->nt_hash);
+ if (ret) goto done;
+
+ ret = export_data_buffer(&state,
+ cred->cred.user.lm_hash.data,
+ cred->cred.user.lm_hash.length,
+ &ecred->lm_hash);
+ if (ret) goto done;
+ break;
+ case GSSNTLM_CRED_SERVER:
+ ecred->type = EXP_CRED_SERVER;
+
+ ret = export_name(&state, &cred->cred.server.name, &ecred->name);
+ if (ret) goto done;
+ break;
+ }
+
+ ret = 0;
+
+done:
+ if (ret) {
+ *minor_status = ret;
+ free(state.exp_struct);
+ return GSS_S_FAILURE;
+ } else {
+ token->value = state.exp_struct;
+ token->length = state.exp_len;
+ return GSS_S_COMPLETE;
+ }
+}
+
+uint32_t gssntlm_import_cred(uint32_t *minor_status,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle)
+{
+ struct gssntlm_cred *cred;
+ struct export_state state;
+ struct export_cred *ecred;
+ uint32_t maj;
+
+ if (minor_status == NULL) {
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+ }
+ *minor_status = 0;
+
+ if (token == NULL) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+
+ if (token->length < sizeof(struct export_cred)) {
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ if (cred_handle == NULL) {
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+ }
+
+ cred = calloc(1, sizeof(struct gssntlm_cred));
+ if (!cred) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ state.exp_struct = token->value;
+ state.exp_len = token->length;
+ ecred = (struct export_cred *)state.exp_struct;
+ state.exp_data = (void *)ecred->data - (void *)ecred;
+ state.exp_ptr = 0;
+
+ if (ecred->version != le16toh(1)) {
+ maj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
+ switch (ecred->type) {
+ case EXP_CRED_NONE:
+ cred->type = GSSNTLM_CRED_NONE;
+ break;
+ case EXP_CRED_ANON:
+ cred->type = GSSNTLM_CRED_ANON;
+ break;
+ case EXP_CRED_USER:
+ cred->type = GSSNTLM_CRED_USER;
+ maj = import_name(minor_status, &state, &ecred->name,
+ &cred->cred.user.user);
+ if (maj != GSS_S_COMPLETE) goto done;
+
+ if (ecred->nt_hash.len > 16 || ecred->lm_hash.len > 16) {
+ maj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
+ maj = import_data_buffer(minor_status, &state,
+ (uint8_t **)&cred->cred.user.nt_hash.data,
+ &cred->cred.user.nt_hash.length,
+ false, &ecred->nt_hash, false);
+ if (maj != GSS_S_COMPLETE) goto done;
+
+ maj = import_data_buffer(minor_status, &state,
+ (uint8_t **)&cred->cred.user.lm_hash.data,
+ &cred->cred.user.lm_hash.length,
+ false, &ecred->lm_hash, false);
+ if (maj != GSS_S_COMPLETE) goto done;
+ break;
+ case EXP_CRED_SERVER:
+ cred->type = GSSNTLM_CRED_SERVER;
+ maj = import_name(minor_status, &state, &ecred->name,
+ &cred->cred.server.name);
+ if (maj != GSS_S_COMPLETE) goto done;
+ break;
+ default:
+ maj = GSS_S_DEFECTIVE_TOKEN;
+ break;
+ }
+
+ maj = GSS_S_COMPLETE;
+
+done:
+ if (maj == GSS_S_COMPLETE) {
+ *cred_handle = (gss_cred_id_t)cred;
+ } else {
+ uint32_t min;
+ gssntlm_release_cred(&min, (gss_cred_id_t *)&cred);
+ }
+ return maj;
+}
diff --git a/src/gss_spi.c b/src/gss_spi.c
index 03cb7ef..bc681e9 100644
--- a/src/gss_spi.c
+++ b/src/gss_spi.c
@@ -346,3 +346,17 @@ OM_uint32 gss_import_sec_context(OM_uint32 *minor_status,
interprocess_token,
context_handle);
}
+
+OM_uint32 gss_export_cred(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_buffer_t token)
+{
+ return gssntlm_export_cred(minor_status, cred_handle, token);
+}
+
+OM_uint32 gss_import_cred(OM_uint32 *minor_status,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle)
+{
+ return gssntlm_import_cred(minor_status, token, cred_handle);
+}