GSS_C_DCE_STYLE_FLAG
Stefan (metze) Metzmacher
metze at samba.org
Mon Dec 6 17:52:32 GMT 2004
Hi Love,
there's a little patch to implement server code for handling the GSS_C_DCE_STYLE_FLAG
I'm not sure if this is all correct. (is the krb5_rd_rep() correct in use here?)
How can I add GSS_C_* flags in the client code?
--
metze
Stefan Metzmacher <metze at samba.org> www.samba.org
-------------- next part --------------
Index: libcli/auth/kerberos_verify.c
===================================================================
--- libcli/auth/kerberos_verify.c (revision 4081)
+++ libcli/auth/kerberos_verify.c (working copy)
@@ -244,6 +244,40 @@
return ret;
}
+static krb5_error_code gssapi_krb5_8003_checksum_flags(krb5_context context, const Checksum *cksum, uint32_t *_flags)
+{
+ krb5_error_code ret = 0;
+ uint8_t *p;
+ uint32_t hash_length;
+ uint8_t hash[16];
+ uint32_t flags;
+
+ if(cksum->cksumtype != 0x8003 || cksum->checksum.length < 24) {
+ return GSS_S_BAD_BINDINGS;
+ }
+
+ p = cksum->checksum.data;
+
+ hash_length = IVAL(p, 0);
+ p += 4;
+
+ if (hash_length != sizeof(hash)) {
+ return GSS_S_BAD_BINDINGS;
+ }
+
+ /* TODO: check hash! */
+
+ p += sizeof(hash);
+
+ flags = IVAL(p, 0);
+
+DEBUG(0,("gss_flags: 0x%08X\n", flags));
+
+ *_flags = flags;
+
+ return ret;
+}
+
/**********************************************************************************
Verify an incoming ticket and parse out the principal name and
authorization_data if available.
@@ -261,7 +295,9 @@
krb5_data packet;
krb5_ticket *tkt = NULL;
krb5_rcache rcache = NULL;
+ krb5_authenticator authenticator;
int ret;
+ uint32 flags = 0;
krb5_principal host_princ = NULL;
char *host_princ_s = NULL;
@@ -332,17 +368,36 @@
goto out;
}
- ret = krb5_mk_rep(context, auth_context, &packet);
+ ret = krb5_auth_con_getauthenticator(context, auth_context, &authenticator);
if (ret) {
- DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
+ DEBUG(3,("ads_verify_ticket: Failed to get authenticator (%s)\n",
error_message(ret)));
goto out;
}
- *ap_rep = data_blob_talloc(mem_ctx, packet.data, packet.length);
- SAFE_FREE(packet.data);
- packet.length = 0;
+ ret = gssapi_krb5_8003_checksum_flags(context, authenticator->cksum, &flags);
+ if (ret) {
+ DEBUG(3,("ads_verify_ticket: Failed to get authenticator (%s)\n",
+ error_message(ret)));
+ goto out;
+ }
+ if (flags & GSS_C_MUTUAL_FLAG) {
+ ret = krb5_mk_rep(context, auth_context, &packet);
+ if (ret) {
+ DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
+ error_message(ret)));
+ goto out;
+ }
+
+ *ap_rep = data_blob_talloc(mem_ctx, packet.data, packet.length);
+ SAFE_FREE(packet.data);
+ packet.length = 0;
+ } else {
+ DEBUG(3,("no mutal: 0x%08X & 0x%08X\n", flags, GSS_C_MUTUAL_FLAG));
+ *ap_rep = data_blob(NULL, 0);
+ }
+
#if 0
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
#endif
@@ -375,7 +430,14 @@
goto out;
}
- sret = NT_STATUS_OK;
+#ifndef GSS_C_DCE_STYLE_FLAG
+#define GSS_C_DCE_STYLE_FLAG 0x1000
+#endif
+ if (flags & GSS_C_DCE_STYLE_FLAG) {
+ sret = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ } else {
+ sret = NT_STATUS_OK;
+ }
out:
@@ -383,11 +445,8 @@
release_server_mutex();
}
- if (!NT_STATUS_IS_OK(sret)) {
+ if (!NT_STATUS_EQUAL(sret, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(sret)) {
data_blob_free(auth_data);
- }
-
- if (!NT_STATUS_IS_OK(sret)) {
data_blob_free(ap_rep);
}
@@ -404,4 +463,29 @@
return sret;
}
+
+ NTSTATUS ads_krb5_rd_rep(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_auth_context auth_context,
+ const DATA_BLOB *ap_rep_in)
+{
+ krb5_data packet;
+ krb5_ap_rep_enc_part *ap_rep = NULL;
+ int ret;
+
+ ZERO_STRUCT(packet);
+
+ packet.length = ap_rep_in->length;
+ packet.data = (krb5_pointer)ap_rep_in->data;
+
+ ret = krb5_rd_rep(context, auth_context, &packet, &ap_rep);
+ if (ret) {
+ DEBUG(3,("ads_krb5_rd_rep: Failed to handle ap_rep (%s)\n",
+ error_message(ret)));
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ return NT_STATUS_OK;
+}
+
#endif /* HAVE_KRB5 */
Index: libcli/auth/gensec.c
===================================================================
--- libcli/auth/gensec.c (revision 4081)
+++ libcli/auth/gensec.c (working copy)
@@ -232,6 +232,7 @@
DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
return NT_STATUS_INVALID_PARAMETER;
}
+ gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
}
Index: libcli/auth/gensec.h
===================================================================
--- libcli/auth/gensec.h (revision 4081)
+++ libcli/auth/gensec.h (working copy)
@@ -44,6 +44,7 @@
#define GENSEC_FEATURE_SESSION_KEY 0x00000001
#define GENSEC_FEATURE_SIGN 0x00000002
#define GENSEC_FEATURE_SEAL 0x00000004
+#define GENSEC_FEATURE_DCE_STYLE 0x00000008
/* GENSEC mode */
enum gensec_role
Index: libcli/auth/kerberos.h
===================================================================
--- libcli/auth/kerberos.h (revision 4081)
+++ libcli/auth/kerberos.h (working copy)
@@ -81,6 +81,10 @@
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
krb5_keyblock *keyblock);
+NTSTATUS ads_krb5_rd_rep(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_auth_context auth_context,
+ const DATA_BLOB *ap_rep_in);
int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, const char *principal, const char *password, time_t *expire_time, time_t *kdc_time);
#endif /* HAVE_KRB5 */
Index: libcli/auth/gensec_krb5.c
===================================================================
--- libcli/auth/gensec_krb5.c (revision 4081)
+++ libcli/auth/gensec_krb5.c (working copy)
@@ -35,6 +35,7 @@
enum GENSEC_KRB5_STATE {
GENSEC_KRB5_SERVER_START,
+ GENSEC_KRB5_SERVER_DCE_STYLE,
GENSEC_KRB5_CLIENT_START,
GENSEC_KRB5_CLIENT_MUTUAL_AUTH,
GENSEC_KRB5_DONE
@@ -50,6 +51,7 @@
krb5_data ticket;
krb5_keyblock krb5_keyblock;
char *peer_principal;
+ BOOL wrap;
};
#ifdef KRB5_DO_VERIFY_PAC
@@ -521,6 +523,7 @@
/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
+ gensec_krb5_state->wrap = False;
nt_status = ads_verify_ticket(out_mem_ctx,
gensec_krb5_state->krb5_context,
gensec_krb5_state->krb5_auth_context,
@@ -528,6 +531,7 @@
&principal, &pac, &unwrapped_out,
&gensec_krb5_state->krb5_keyblock);
} else {
+ gensec_krb5_state->wrap = True;
/* TODO: check the tok_id */
nt_status = ads_verify_ticket(out_mem_ctx,
gensec_krb5_state->krb5_context,
@@ -537,7 +541,7 @@
&gensec_krb5_state->krb5_keyblock);
}
- if (!NT_STATUS_IS_OK(nt_status)) {
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
@@ -545,16 +549,50 @@
gensec_krb5_state->pac = data_blob_talloc_reference(gensec_krb5_state, &pac);
}
+ /* wrap that up in a nice GSS-API wrapping */
+ if (gensec_krb5_state->wrap) {
+ *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
+ } else {
+ *out = unwrapped_out;
+ }
+
+ gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state, principal);
if (NT_STATUS_IS_OK(nt_status)) {
gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
- /* wrap that up in a nice GSS-API wrapping */
-#ifndef GENSEC_SEND_UNWRAPPED_KRB5
- *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
-#else
+ } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ gensec_krb5_state->state_position = GENSEC_KRB5_SERVER_DCE_STYLE;
+ }
+ return nt_status;
+ }
+ case GENSEC_KRB5_SERVER_DCE_STYLE: {
+ DATA_BLOB unwrapped_in;
+ DATA_BLOB unwrapped_out = data_blob(NULL, 0);
+ uint8 tok_id[2];
+
+ if (!in.data) {
*out = unwrapped_out;
-#endif
- gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state, principal);
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
+ if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
+ gensec_krb5_state->wrap = False;
+ nt_status = ads_krb5_rd_rep(out_mem_ctx,
+ gensec_krb5_state->krb5_context,
+ gensec_krb5_state->krb5_auth_context,
+ &in);
+ } else {
+ gensec_krb5_state->wrap = True;
+ /* TODO: check the tok_id */
+ nt_status = ads_krb5_rd_rep(out_mem_ctx,
+ gensec_krb5_state->krb5_context,
+ gensec_krb5_state->krb5_auth_context,
+ &unwrapped_in);
}
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+ gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
return nt_status;
}
case GENSEC_KRB5_DONE:
More information about the samba-technical
mailing list