summaryrefslogtreecommitdiff
path: root/source4/utils
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-06-20 00:58:09 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:56:44 -0500
commitbe081037e09bb78c0308cd6c7a5d7ae563678b7c (patch)
tree4bdabbe93653433e696d4abc4ac3b2991e59aed6 /source4/utils
parent8cb41badd4349b7d9d78ff8e25143929522e4749 (diff)
downloadsamba-be081037e09bb78c0308cd6c7a5d7ae563678b7c.tar.gz
samba-be081037e09bb78c0308cd6c7a5d7ae563678b7c.tar.bz2
samba-be081037e09bb78c0308cd6c7a5d7ae563678b7c.zip
r1200: Add 'gensec', our generic security layer.
This layer is used for DCERPC security, as well as ntlm_auth at this time. It expect things like SASL and the CIFS layer to use it as well. The particular purpose of this layer is to introduce SPENGO, which needs generic access to the actual implementation mechanisms. Schannel, due to it's 'interesting' setup properties is in GENSEC, but is only in the RPC code. Andrew Bartlett (This used to be commit 902af49006fb8cfecaadd3cc0c10e2e542083fb1)
Diffstat (limited to 'source4/utils')
-rw-r--r--source4/utils/ntlm_auth.c832
1 files changed, 70 insertions, 762 deletions
diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c
index d70b0b5d2b..7690a549f7 100644
--- a/source4/utils/ntlm_auth.c
+++ b/source4/utils/ntlm_auth.c
@@ -34,7 +34,6 @@ enum stdio_helper_mode {
SQUID_2_5_BASIC,
SQUID_2_5_NTLMSSP,
NTLMSSP_CLIENT_1,
- GSS_SPNEGO,
GSS_SPNEGO_CLIENT,
NTLM_SERVER_1,
NUM_HELPER_MODES
@@ -53,14 +52,8 @@ static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode
static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode,
char *buf, int length);
-static void manage_client_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length);
-
-static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length);
-
-static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length);
+static void manage_gensec_client_request (enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode,
char *buf, int length);
@@ -73,9 +66,8 @@ static const struct {
{ SQUID_2_4_BASIC, "squid-2.4-basic", manage_squid_basic_request},
{ SQUID_2_5_BASIC, "squid-2.5-basic", manage_squid_basic_request},
{ SQUID_2_5_NTLMSSP, "squid-2.5-ntlmssp", manage_squid_ntlmssp_request},
- { NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_client_ntlmssp_request},
- { GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
- { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
+ { NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_gensec_client_request},
+ { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gensec_client_request},
{ NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
{ NUM_HELPER_MODES, NULL, NULL}
};
@@ -218,52 +210,6 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *u
return nt_status;
}
-static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntlmssp_state)
-{
- NTSTATUS status;
- if ( (opt_username == NULL) || (opt_domain == NULL) ) {
- DEBUG(1, ("Need username and domain for NTLMSSP\n"));
- return status;
- }
-
- status = ntlmssp_client_start(client_ntlmssp_state);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not start NTLMSSP client: %s\n",
- nt_errstr(status)));
- ntlmssp_end(client_ntlmssp_state);
- return status;
- }
-
- status = ntlmssp_set_username(*client_ntlmssp_state, opt_username);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not set username: %s\n",
- nt_errstr(status)));
- ntlmssp_end(client_ntlmssp_state);
- return status;
- }
-
- status = ntlmssp_set_domain(*client_ntlmssp_state, opt_domain);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not set domain: %s\n",
- nt_errstr(status)));
- ntlmssp_end(client_ntlmssp_state);
- return status;
- }
-
- status = ntlmssp_set_password(*client_ntlmssp_state, opt_password);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not set password: %s\n",
- nt_errstr(status)));
- ntlmssp_end(client_ntlmssp_state);
- return status;
- }
- return NT_STATUS_OK;
-}
-
static NTSTATUS ntlm_auth_start_ntlmssp_server(struct ntlmssp_state **ntlmssp_state)
{
NTSTATUS status = ntlmssp_server_start(ntlmssp_state);
@@ -367,102 +313,6 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
data_blob_free(&request);
}
-static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length)
-{
- static struct ntlmssp_state *ntlmssp_state = NULL;
- DATA_BLOB request, reply;
- NTSTATUS nt_status;
- BOOL first = False;
-
- if (strlen(buf) < 2) {
- DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if (strlen(buf) > 3) {
- request = base64_decode_data_blob(buf + 3);
- } else {
- request = data_blob(NULL, 0);
- }
-
- if (strncmp(buf, "PW ", 3) == 0) {
- /* We asked for a password and obviously got it :-) */
-
- opt_password = strndup((const char *)request.data, request.length);
-
- if (opt_password == NULL) {
- DEBUG(1, ("Out of memory\n"));
- x_fprintf(x_stdout, "BH\n");
- data_blob_free(&request);
- return;
- }
-
- x_fprintf(x_stdout, "OK\n");
- data_blob_free(&request);
- return;
- }
-
- if (opt_password == NULL) {
-
- /* Request a password from the calling process. After
- sending it, the calling process should retry asking for the negotiate. */
-
- DEBUG(10, ("Requesting password\n"));
- x_fprintf(x_stdout, "PW\n");
- return;
- }
-
- if (strncmp(buf, "YR", 2) == 0) {
- if (ntlmssp_state)
- ntlmssp_end(&ntlmssp_state);
- } else if (strncmp(buf, "TT", 2) == 0) {
-
- } else {
- DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if (!ntlmssp_state) {
- if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_client(&ntlmssp_state))) {
- x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
- return;
- }
- first = True;
- }
-
- DEBUG(10, ("got NTLMSSP packet:\n"));
- dump_data(10, (const char *)request.data, request.length);
-
- nt_status = ntlmssp_update(ntlmssp_state, NULL, request, &reply);
-
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- char *reply_base64 = base64_encode_data_blob(reply);
- if (first) {
- x_fprintf(x_stdout, "YR %s\n", reply_base64);
- } else {
- x_fprintf(x_stdout, "KK %s\n", reply_base64);
- }
- SAFE_FREE(reply_base64);
- data_blob_free(&reply);
- DEBUG(10, ("NTLMSSP challenge\n"));
- } else if (NT_STATUS_IS_OK(nt_status)) {
- x_fprintf(x_stdout, "AF\n");
- DEBUG(10, ("NTLMSSP OK!\n"));
- if (ntlmssp_state)
- ntlmssp_end(&ntlmssp_state);
- } else {
- x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
- DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status)));
- if (ntlmssp_state)
- ntlmssp_end(&ntlmssp_state);
- }
-
- data_blob_free(&request);
-}
-
static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
@@ -490,654 +340,111 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
}
}
-static void offer_gss_spnego_mechs(void) {
-
- DATA_BLOB token;
- struct spnego_data spnego;
- ssize_t len;
- char *reply_base64;
-
- pstring principal;
- pstring myname_lower;
-
- ZERO_STRUCT(spnego);
-
- pstrcpy(myname_lower, global_myname());
- strlower_m(myname_lower);
-
- pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm());
-
- /* Server negTokenInit (mech offerings) */
- spnego.type = SPNEGO_NEG_TOKEN_INIT;
- spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 3);
-#ifdef HAVE_KRB5
- spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD);
- spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP);
- spnego.negTokenInit.mechTypes[2] = NULL;
-#else
- spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP);
- spnego.negTokenInit.mechTypes[1] = NULL;
-#endif
-
-
- spnego.negTokenInit.mechListMIC = data_blob(principal,
- strlen(principal));
-
- len = write_spnego_data(&token, &spnego);
- free_spnego_data(&spnego);
-
- if (len == -1) {
- DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- reply_base64 = base64_encode_data_blob(token);
- x_fprintf(x_stdout, "TT %s *\n", reply_base64);
-
- SAFE_FREE(reply_base64);
- data_blob_free(&token);
- DEBUG(10, ("sent SPNEGO negTokenInit\n"));
- return;
-}
-
-static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length)
+static void manage_gensec_client_request(enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length)
{
- static struct ntlmssp_state *ntlmssp_state = NULL;
- struct spnego_data request, response;
- DATA_BLOB token;
- NTSTATUS status;
- ssize_t len;
-
- char *user = NULL;
- char *domain = NULL;
-
- const char *reply_code;
- char *reply_base64;
- pstring reply_argument;
+ DATA_BLOB in;
+ DATA_BLOB out;
+ char *out_base64;
+ static struct gensec_security gensec_state;
+ NTSTATUS nt_status;
+ BOOL first = False;
if (strlen(buf) < 2) {
- DEBUG(1, ("SPENGO query [%s] invalid", buf));
+ DEBUG(1, ("query [%s] invalid", buf));
x_fprintf(x_stdout, "BH\n");
return;
}
- if (strncmp(buf, "YR", 2) == 0) {
- if (ntlmssp_state)
- ntlmssp_end(&ntlmssp_state);
- } else if (strncmp(buf, "KK", 2) == 0) {
-
- } else {
- DEBUG(1, ("SPENGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if ( (strlen(buf) == 2)) {
-
- /* no client data, get the negTokenInit offering
- mechanisms */
-
- offer_gss_spnego_mechs();
- return;
- }
-
- /* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */
-
- if (strlen(buf) <= 3) {
- DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- token = base64_decode_data_blob(buf + 3);
- len = read_spnego_data(token, &request);
- data_blob_free(&token);
-
- if (len == -1) {
- DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if (request.type == SPNEGO_NEG_TOKEN_INIT) {
-
- /* Second request from Client. This is where the
- client offers its mechanism to use. */
-
- if ( (request.negTokenInit.mechTypes == NULL) ||
- (request.negTokenInit.mechTypes[0] == NULL) ) {
- DEBUG(1, ("Client did not offer any mechanism"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) {
-
- if ( request.negTokenInit.mechToken.data == NULL ) {
- DEBUG(1, ("Client did not provide NTLMSSP data\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if ( ntlmssp_state != NULL ) {
- DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
- "already got one\n"));
- x_fprintf(x_stdout, "BH\n");
- ntlmssp_end(&ntlmssp_state);
- return;
- }
-
- if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) {
- x_fprintf(x_stdout, "BH %s\n", nt_errstr(status));
- return;
- }
-
- DEBUG(10, ("got NTLMSSP packet:\n"));
- dump_data(10, (const char *)request.negTokenInit.mechToken.data,
- request.negTokenInit.mechToken.length);
-
- response.type = SPNEGO_NEG_TOKEN_TARG;
- response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP);
- response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
-
- status = ntlmssp_update(ntlmssp_state,
- NULL,
- request.negTokenInit.mechToken,
- &response.negTokenTarg.responseToken);
- }
-
-#ifdef HAVE_KRB5
- if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) {
-
- char *principal;
- DATA_BLOB auth_data;
- DATA_BLOB ap_rep;
- DATA_BLOB session_key;
-
- if ( request.negTokenInit.mechToken.data == NULL ) {
- DEBUG(1, ("Client did not provide Kerberos data\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- response.type = SPNEGO_NEG_TOKEN_TARG;
- response.negTokenTarg.supportedMech = strdup(OID_KERBEROS5_OLD);
- response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
- response.negTokenTarg.responseToken = data_blob(NULL, 0);
-
- status = ads_verify_ticket(lp_realm(),
- &request.negTokenInit.mechToken,
- &principal, &auth_data, &ap_rep,
- &session_key);
-
- /* Now in "principal" we have the name we are
- authenticated as. */
-
- if (NT_STATUS_IS_OK(status)) {
-
- domain = strchr(principal, '@');
-
- if (domain == NULL) {
- DEBUG(1, ("Did not get a valid principal "
- "from ads_verify_ticket\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- *domain++ = '\0';
- domain = strdup(domain);
- user = strdup(principal);
-
- data_blob_free(&ap_rep);
- data_blob_free(&auth_data);
-
- SAFE_FREE(principal);
- }
- }
-#endif
-
- } else {
-
- if ( (request.negTokenTarg.supportedMech == NULL) ||
- ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) {
- /* Kerberos should never send a negTokenTarg, OID_NTLMSSP
- is the only one we support that sends this stuff */
- DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n",
- request.negTokenTarg.supportedMech));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if (request.negTokenTarg.responseToken.data == NULL) {
- DEBUG(1, ("Got a negTokenTarg without a responseToken!\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- status = ntlmssp_update(ntlmssp_state,
- NULL,
- request.negTokenTarg.responseToken,
- &response.negTokenTarg.responseToken);
-
- response.type = SPNEGO_NEG_TOKEN_TARG;
- response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP);
- response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
-
- if (NT_STATUS_IS_OK(status)) {
- user = strdup(ntlmssp_state->user);
- domain = strdup(ntlmssp_state->domain);
- ntlmssp_end(&ntlmssp_state);
- }
- }
-
- free_spnego_data(&request);
-
- if (NT_STATUS_IS_OK(status)) {
- response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
- reply_code = "AF";
- pstr_sprintf(reply_argument, "%s\\%s", domain, user);
- } else if (NT_STATUS_EQUAL(status,
- NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
- reply_code = "TT";
- pstr_sprintf(reply_argument, "*");
+ if (strlen(buf) > 3) {
+ in = base64_decode_data_blob(buf + 3);
} else {
- response.negTokenTarg.negResult = SPNEGO_REJECT;
- reply_code = "NA";
- pstrcpy(reply_argument, nt_errstr(status));
- }
-
- SAFE_FREE(user);
- SAFE_FREE(domain);
-
- len = write_spnego_data(&token, &response);
- free_spnego_data(&response);
-
- if (len == -1) {
- DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- reply_base64 = base64_encode_data_blob(token);
-
- x_fprintf(x_stdout, "%s %s %s\n",
- reply_code, reply_base64, reply_argument);
-
- SAFE_FREE(reply_base64);
- data_blob_free(&token);
-
- return;
-}
-
-static struct ntlmssp_state *client_ntlmssp_state = NULL;
-
-static BOOL manage_client_ntlmssp_init(struct spnego_data spnego)
-{
- NTSTATUS status;
- DATA_BLOB null_blob = data_blob(NULL, 0);
- DATA_BLOB to_server;
- char *to_server_base64;
- const char *my_mechs[] = {OID_NTLMSSP, NULL};
-
- DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n"));
-
- if (client_ntlmssp_state != NULL) {
- DEBUG(1, ("Request for initial SPNEGO request where "
- "we already have a state\n"));
- return False;
- }
-
- if (!client_ntlmssp_state) {
- if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_client(&client_ntlmssp_state))) {
- x_fprintf(x_stdout, "BH %s\n", nt_errstr(status));
- return False;
- }
- }
-
-
- if (opt_password == NULL) {
-
- /* Request a password from the calling process. After
- sending it, the calling process should retry with
- the negTokenInit. */
-
- DEBUG(10, ("Requesting password\n"));
- x_fprintf(x_stdout, "PW\n");
- return True;
- }
-
- spnego.type = SPNEGO_NEG_TOKEN_INIT;
- spnego.negTokenInit.mechTypes = my_mechs;
- spnego.negTokenInit.reqFlags = 0;
- spnego.negTokenInit.mechListMIC = null_blob;
-
- status = ntlmssp_update(client_ntlmssp_state,
- NULL,
- null_blob,
- &spnego.negTokenInit.mechToken);
-
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n",
- nt_errstr(status)));
- ntlmssp_end(&client_ntlmssp_state);
- return False;
- }
-
- write_spnego_data(&to_server, &spnego);
- data_blob_free(&spnego.negTokenInit.mechToken);
-
- to_server_base64 = base64_encode_data_blob(to_server);
- data_blob_free(&to_server);
- x_fprintf(x_stdout, "KK %s\n", to_server_base64);
- SAFE_FREE(to_server_base64);
- return True;
-}
-
-static void manage_client_ntlmssp_targ(struct spnego_data spnego)
-{
- NTSTATUS status;
- DATA_BLOB null_blob = data_blob(NULL, 0);
- DATA_BLOB request;
- DATA_BLOB to_server;
- char *to_server_base64;
-
- DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n"));
-
- if (client_ntlmssp_state == NULL) {
- DEBUG(1, ("Got NTLMSSP tArg without a client state\n"));
- x_fprintf(x_stdout, "BH\n");
- ntlmssp_end(&client_ntlmssp_state);
- return;
- }
-
- if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) {
- x_fprintf(x_stdout, "NA\n");
- ntlmssp_end(&client_ntlmssp_state);
- return;
- }
-
- if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) {
- x_fprintf(x_stdout, "AF\n");
- ntlmssp_end(&client_ntlmssp_state);
- return;
- }
-
- status = ntlmssp_update(client_ntlmssp_state,
- NULL,
- spnego.negTokenTarg.responseToken,
- &request);
-
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from "
- "ntlmssp_update, got: %s\n",
- nt_errstr(status)));
- x_fprintf(x_stdout, "BH\n");
- data_blob_free(&request);
- ntlmssp_end(&client_ntlmssp_state);
- return;
- }
-
- spnego.type = SPNEGO_NEG_TOKEN_TARG;
- spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
- spnego.negTokenTarg.supportedMech = OID_NTLMSSP;
- spnego.negTokenTarg.responseToken = request;
- spnego.negTokenTarg.mechListMIC = null_blob;
-
- write_spnego_data(&to_server, &spnego);
- data_blob_free(&request);
-
- to_server_base64 = base64_encode_data_blob(to_server);
- data_blob_free(&to_server);
- x_fprintf(x_stdout, "KK %s\n", to_server_base64);
- SAFE_FREE(to_server_base64);
- return;
-}
-
-#ifdef HAVE_KRB5
-
-static BOOL manage_client_krb5_init(struct spnego_data spnego)
-{
- char *principal;
- DATA_BLOB tkt, to_server;
- DATA_BLOB session_key_krb5 = data_blob(NULL, 0);
- struct spnego_data reply;
- char *reply_base64;
- int retval;
-
- const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
- ssize_t len;
-
- if ( (spnego.negTokenInit.mechListMIC.data == NULL) ||
- (spnego.negTokenInit.mechListMIC.length == 0) ) {
- DEBUG(1, ("Did not get a principal for krb5\n"));
- return False;
+ in = data_blob(NULL, 0);
}
- principal = malloc(spnego.negTokenInit.mechListMIC.length+1);
-
- if (principal == NULL) {
- DEBUG(1, ("Could not malloc principal\n"));
- return False;
- }
-
- memcpy(principal, spnego.negTokenInit.mechListMIC.data,
- spnego.negTokenInit.mechListMIC.length);
- principal[spnego.negTokenInit.mechListMIC.length] = '\0';
-
- retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
-
- if (retval) {
-
- pstring user;
-
- /* Let's try to first get the TGT, for that we need a
- password. */
-
- if (opt_password == NULL) {
- DEBUG(10, ("Requesting password\n"));
- x_fprintf(x_stdout, "PW\n");
- return True;
- }
-
- pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
-
- if ((retval = kerberos_kinit_password(user, opt_password,
- 0, NULL))) {
- DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
- return False;
- }
-
- retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
-
- if (retval) {
- DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
- return False;
- }
- }
-
- data_blob_free(&session_key_krb5);
-
- ZERO_STRUCT(reply);
-
- reply.type = SPNEGO_NEG_TOKEN_INIT;
- reply.negTokenInit.mechTypes = my_mechs;
- reply.negTokenInit.reqFlags = 0;
- reply.negTokenInit.mechToken = tkt;
- reply.negTokenInit.mechListMIC = data_blob(NULL, 0);
-
- len = write_spnego_data(&to_server, &reply);
- data_blob_free(&tkt);
-
- if (len == -1) {
- DEBUG(1, ("Could not write SPNEGO data blob\n"));
- return False;
- }
-
- reply_base64 = base64_encode_data_blob(to_server);
- x_fprintf(x_stdout, "KK %s *\n", reply_base64);
-
- SAFE_FREE(reply_base64);
- data_blob_free(&to_server);
- DEBUG(10, ("sent GSS-SPNEGO KERBEROS5 negTokenInit\n"));
- return True;
-}
-
-static void manage_client_krb5_targ(struct spnego_data spnego)
-{
- switch (spnego.negTokenTarg.negResult) {
- case SPNEGO_ACCEPT_INCOMPLETE:
- DEBUG(1, ("Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE\n"));
- x_fprintf(x_stdout, "BH\n");
- break;
- case SPNEGO_ACCEPT_COMPLETED:
- DEBUG(10, ("Accept completed\n"));
- x_fprintf(x_stdout, "AF\n");
- break;
- case SPNEGO_REJECT:
- DEBUG(10, ("Rejected\n"));
- x_fprintf(x_stdout, "NA\n");
- break;
- default:
- DEBUG(1, ("Got an invalid negTokenTarg\n"));
- x_fprintf(x_stdout, "AF\n");
- }
-}
-
-#endif
-
-static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode,
- char *buf, int length)
-{
- DATA_BLOB request;
- struct spnego_data spnego;
- ssize_t len;
-
- if (strlen(buf) <= 3) {
- DEBUG(1, ("SPNEGO query [%s] too short\n", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- request = base64_decode_data_blob(buf+3);
-
if (strncmp(buf, "PW ", 3) == 0) {
/* We asked for a password and obviously got it :-) */
- opt_password = strndup((const char *)request.data, request.length);
+ opt_password = strndup((const char *)in.data, in.length);
if (opt_password == NULL) {
DEBUG(1, ("Out of memory\n"));
x_fprintf(x_stdout, "BH\n");
- data_blob_free(&request);
+ data_blob_free(&in);
return;
}
x_fprintf(x_stdout, "OK\n");
- data_blob_free(&request);
+ data_blob_free(&in);
return;
}
-
- if ( (strncmp(buf, "TT ", 3) != 0) &&
+ if (strncmp(buf, "YR", 2) == 0) {
+ if (gensec_state.ops) {
+ gensec_state.ops->end(&gensec_state);
+ gensec_state.ops = NULL;
+ }
+ } else if ( (strncmp(buf, "TT ", 3) != 0) &&
(strncmp(buf, "AF ", 3) != 0) &&
(strncmp(buf, "NA ", 3) != 0) ) {
DEBUG(1, ("SPNEGO request [%s] invalid\n", buf));
x_fprintf(x_stdout, "BH\n");
- data_blob_free(&request);
+ data_blob_free(&in);
return;
}
- /* So we got a server challenge to generate a SPNEGO
- client-to-server request... */
-
- len = read_spnego_data(request, &spnego);
- data_blob_free(&request);
-
- if (len == -1) {
- DEBUG(1, ("Could not read SPNEGO data for [%s]\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ if (!opt_password) {
+ x_fprintf(x_stdout, "PW\n");
+ data_blob_free(&in);
return;
}
- if (spnego.type == SPNEGO_NEG_TOKEN_INIT) {
-
- /* The server offers a list of mechanisms */
-
- char **mechType = spnego.negTokenInit.mechTypes;
-
- while (*mechType != NULL) {
-
-#ifdef HAVE_KRB5
- if ( (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) ||
- (strcmp(*mechType, OID_KERBEROS5) == 0) ) {
- if (manage_client_krb5_init(spnego))
- goto out;
- }
-#endif
-
- if (strcmp(*mechType, OID_NTLMSSP) == 0) {
- if (manage_client_ntlmssp_init(spnego))
- goto out;
- }
-
- mechType++;
+ /* setup gensec */
+ if (!gensec_state.ops) {
+ if (stdio_helper_mode == GSS_SPNEGO_CLIENT) {
+ gensec_state.ops = gensec_security_by_oid(OID_SPNEGO);
+ } else if (stdio_helper_mode == NTLMSSP_CLIENT_1) {
+ gensec_state.ops = gensec_security_by_oid(OID_NTLMSSP);
+ } else {
+ exit(1);
}
+ gensec_state.user.name = opt_username;
+ gensec_state.user.domain = opt_domain;
+ gensec_state.user.password = opt_password;
+ nt_status = gensec_state.ops->client_start(&gensec_state);
- DEBUG(1, ("Server offered no compatible mechanism\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("SPENGO login failed to initialise: %s\n", nt_errstr(nt_status)));
+ x_fprintf(x_stdout, "BH\n");
+ return;
+ }
+ if (!in.length) {
+ first = True;
+ }
}
+
+ /* update */
- if (spnego.type == SPNEGO_NEG_TOKEN_TARG) {
-
- if (spnego.negTokenTarg.supportedMech == NULL) {
- /* On accept/reject Windows does not send the
- mechanism anymore. Handle that here and
- shut down the mechanisms. */
-
- switch (spnego.negTokenTarg.negResult) {
- case SPNEGO_ACCEPT_COMPLETED:
- x_fprintf(x_stdout, "AF\n");
- break;
- case SPNEGO_REJECT:
- x_fprintf(x_stdout, "NA\n");
- break;
- default:
- DEBUG(1, ("Got a negTokenTarg with no mech and an "
- "unknown negResult: %d\n",
- spnego.negTokenTarg.negResult));
- x_fprintf(x_stdout, "BH\n");
- }
-
- ntlmssp_end(&client_ntlmssp_state);
- goto out;
- }
+ nt_status = gensec_state.ops->update(&gensec_state, NULL, in, &out);
+
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- if (strcmp(spnego.negTokenTarg.supportedMech,
- OID_NTLMSSP) == 0) {
- manage_client_ntlmssp_targ(spnego);
- goto out;
+ out_base64 = base64_encode_data_blob(out);
+ if (first) {
+ x_fprintf(x_stdout, "YR %s\n", out_base64);
+ } else {
+ x_fprintf(x_stdout, "KK %s\n", out_base64);
}
+ SAFE_FREE(out_base64);
-#if HAVE_KRB5
- if (strcmp(spnego.negTokenTarg.supportedMech,
- OID_KERBEROS5_OLD) == 0) {
- manage_client_krb5_targ(spnego);
- goto out;
- }
-#endif
+ } else if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("SPENGO login failed: %s\n", nt_errstr(nt_status)));
+ x_fprintf(x_stdout, "BH\n");
+ } else {
+ x_fprintf(x_stdout, "AF\n");
}
- DEBUG(1, ("Got an SPNEGO token I could not handle [%s]!\n", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
-
- out:
- free_spnego_data(&spnego);
return;
}
@@ -1428,6 +735,7 @@ enum {
{ "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"},
{ "domain", 0, POPT_ARG_STRING, &opt_domain, OPT_DOMAIN, "domain name"},
{ "workstation", 0, POPT_ARG_STRING, &opt_workstation, OPT_WORKSTATION, "workstation"},
+ { "username", 0, POPT_ARG_STRING, &opt_username, OPT_PASSWORD, "Username"},
{ "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"},
POPT_COMMON_SAMBA
POPT_TABLEEND
@@ -1469,6 +777,10 @@ enum {
return 1;
}
+ if (opt_domain == NULL) {
+ opt_domain = lp_workgroup();
+ }
+
if (helper_protocol) {
int i;
for (i=0; i<NUM_HELPER_MODES; i++) {
@@ -1492,10 +804,6 @@ enum {
exit(1);
}
- if (opt_domain == NULL) {
- opt_domain = lp_workgroup();
- }
-
if (opt_workstation == NULL) {
opt_workstation = lp_netbios_name();
}