summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/includes.h4
-rw-r--r--source3/libsmb/asn1.c18
-rw-r--r--source3/libsmb/cliconnect.c4
-rw-r--r--source3/libsmb/clikrb5.c4
-rw-r--r--source3/libsmb/clispnego.c23
-rw-r--r--source3/smbd/negprot.c3
-rw-r--r--source3/smbd/sesssetup.c100
7 files changed, 141 insertions, 15 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 3a6282a006..38692d9906 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -365,6 +365,10 @@
#include <iconv.h>
#endif
+#if HAVE_KRB5
+#include <krb5.h>
+#endif
+
/*
* Define VOLATILE if needed.
*/
diff --git a/source3/libsmb/asn1.c b/source3/libsmb/asn1.c
index 59763408cf..a8c0eebb94 100644
--- a/source3/libsmb/asn1.c
+++ b/source3/libsmb/asn1.c
@@ -156,6 +156,24 @@ BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
return !data->has_error;
}
+/* check a BOOLEAN */
+BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
+{
+ uint8 b = 0;
+
+ asn1_read_uint8(data, &b);
+ if (b != ASN1_BOOLEAN) {
+ data->has_error = True;
+ return False;
+ }
+ asn1_read_uint8(data, &b);
+ if (b != v) {
+ data->has_error = True;
+ return False;
+ }
+ return !data->has_error;
+}
+
/* load a ASN1_DATA structure with a lump of data, ready to be parsed */
BOOL asn1_load(ASN1_DATA *data, DATA_BLOB blob)
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 6a01744240..4fba54900d 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -392,6 +392,10 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principle, c
if (!negTokenTarg.data) return False;
+#if 0
+ file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
+#endif
+
blob2 = cli_session_setup_blob(cli, negTokenTarg);
/* we don't need this blob for kerberos */
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 68e941f2aa..51b6e6e8cf 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -22,8 +22,6 @@
#include "includes.h"
#if HAVE_KRB5
-#include <krb5.h>
-
/*
we can't use krb5_mk_req because w2k wants the service to be in a particular format
*/
@@ -105,7 +103,7 @@ DATA_BLOB krb5_get_ticket(char *service, char *realm)
if ((retval = krb5_mk_req2(context,
&auth_context,
- AP_OPTS_MUTUAL_REQUIRED,
+ 0,
service, realm,
ccdef, &packet))) {
DEBUG(1,("krb5_mk_req2 failed\n"));
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 78cae3315a..c421d75913 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -241,6 +241,29 @@ static DATA_BLOB spnego_gen_krb5_wrap(DATA_BLOB ticket)
return ret;
}
+/*
+ parse a krb5 GSS-API wrapper packet giving a ticket
+*/
+BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket)
+{
+ BOOL ret;
+ ASN1_DATA data;
+
+ asn1_load(&data, blob);
+ asn1_start_tag(&data, ASN1_APPLICATION(0));
+ asn1_check_OID(&data, OID_KERBEROS5);
+ asn1_check_BOOLEAN(&data, 0);
+ *ticket = data_blob(data.data, asn1_tag_remaining(&data));
+ asn1_read(&data, ticket->data, ticket->length);
+ asn1_end_tag(&data);
+
+ ret = !data.has_error;
+
+ asn1_free(&data);
+
+ return ret;
+}
+
/*
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index cf14640a72..678156b528 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -164,10 +164,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8])
extern pstring global_myname;
uint8 guid[16];
const char *OIDs[] = {OID_NTLMSSP,
-#if 0
- /* not till we add kerberos in the server */
OID_KERBEROS5_OLD,
-#endif
NULL};
char *principle;
int len;
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index a833b7e706..7eb8f4e694 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -22,6 +22,71 @@
#include "includes.h"
+#if HAVE_KRB5
+/****************************************************************************
+reply to a session setup spnego negotiate packet for kerberos
+****************************************************************************/
+static int reply_spnego_kerberos(connection_struct *conn, char *outbuf,
+ DATA_BLOB *secblob)
+{
+ DATA_BLOB ticket;
+ krb5_context context;
+ krb5_principal server;
+ krb5_auth_context auth_context = NULL;
+ krb5_keytab keytab = NULL;
+ krb5_data packet;
+ krb5_ticket *tkt = NULL;
+ int ret;
+ char *realm, *client;
+ fstring service;
+ extern pstring global_myname;
+
+ realm = lp_realm();
+
+ if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ /* the service is the wins name lowercase with $ tacked on */
+ fstrcpy(service, global_myname);
+ strlower(service);
+ fstrcat(service, "$");
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ ret = krb5_build_principal(context, &server, strlen(realm),
+ realm, service, NULL);
+ if (ret) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ packet.length = ticket.length;
+ packet.data = (krb5_pointer)ticket.data;
+
+ if ((ret = krb5_rd_req(context, &auth_context, &packet,
+ server, keytab, NULL, &tkt))) {
+ DEBUG(3,("krb5_rd_req failed with code %08x\n", ret));
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ if ((ret = krb5_unparse_name(context, tkt->enc_part2->client,
+ &client))) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ DEBUG(3,("Ticket name is [%s]\n", client));
+
+ /* well, if we got a client above then I think we have authenticated the user
+ but fail it for now until I understand it */
+
+
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+}
+#endif
+
/****************************************************************************
send a security blob via a session setup reply
@@ -50,9 +115,6 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
return send_smb(smbd_server_fd(),outbuf);
}
-
-
-
/****************************************************************************
reply to a session setup spnego negotiate packet
****************************************************************************/
@@ -65,6 +127,7 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf,
uint32 ntlmssp_command, neg_flags;
DATA_BLOB sess_key, chal, spnego_chal;
uint8 cryptkey[8];
+ BOOL got_kerberos = False;
/* parse out the OIDs and the first sec blob */
if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -73,20 +136,33 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf,
for (i=0;OIDs[i];i++) {
DEBUG(3,("Got OID %s\n", OIDs[i]));
+ if (strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
+ got_kerberos = True;
+ }
free(OIDs[i]);
}
DEBUG(3,("Got secblob of size %d\n", secblob.length));
+#if HAVE_KRB5
+ if (got_kerberos) {
+ int ret = reply_spnego_kerberos(conn, outbuf, &secblob);
+ data_blob_free(&secblob);
+ return ret;
+ }
+#endif
+
/* parse the NTLMSSP packet */
#if 0
file_save("secblob.dat", secblob.data, secblob.length);
#endif
- msrpc_parse(&secblob, "CddB",
- "NTLMSSP",
- &ntlmssp_command,
- &neg_flags,
- &sess_key);
+ if (!msrpc_parse(&secblob, "CddB",
+ "NTLMSSP",
+ &ntlmssp_command,
+ &neg_flags,
+ &sess_key)) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
data_blob_free(&secblob);
data_blob_free(&sess_key);
@@ -97,7 +173,9 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf,
DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
- last_challenge(cryptkey);
+ if (!last_challenge(cryptkey)) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
/* Give them the challenge. For now, ignore neg_flags and just
return the flags we want. Obviously this is not correct */
@@ -252,6 +330,10 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha
/* pull the spnego blob */
blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
+#if 0
+ file_save("negotiate.dat", blob1.data, blob1.length);
+#endif
+
if (blob1.data[0] == ASN1_APPLICATION(0)) {
/* its a negTokenTarg packet */
ret = reply_spnego_negotiate(conn, outbuf, blob1);