summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-04-12 20:46:13 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:51:12 -0500
commit4dad0782561c063a3b1c477ef029d2ba606bb243 (patch)
tree36825dc9be834370581b047d334c35efdf04ca17
parent298ef0676cb640d73474a6cde2bc142b8464eef7 (diff)
downloadsamba-4dad0782561c063a3b1c477ef029d2ba606bb243.tar.gz
samba-4dad0782561c063a3b1c477ef029d2ba606bb243.tar.bz2
samba-4dad0782561c063a3b1c477ef029d2ba606bb243.zip
r188: Add a new 'helper protocol' to ntlm_auth.
This protocol looks rather like SMTP headers/LDAP: NT-Domain: TESTWG Username: abartlet ... Password: foo Challenge-response passwords are in hexideciaml, while any 'plain' string can be base64 encoded when like this: Password:: Zm9vCg== (the :: indicates it, just like LDAP - I hope) The protocol is not final, so it is #ifdef DEVELOPER for now (so nobody starts to rely on it until I'm happy), but we may as well get this into subversion. My intention is to use this to power the next version of my PPP/ntlm_auth plugin, and hopefully entice a FreeRadius plugin out of the woods. Andrew Bartlett (This used to be commit 8efdd957ba8310515242ba2979ff07130a0b1a3a)
-rw-r--r--source3/utils/ntlm_auth.c204
1 files changed, 202 insertions, 2 deletions
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 45e37dc37f..9e65040107 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -37,6 +37,7 @@ enum stdio_helper_mode {
NTLMSSP_CLIENT_1,
GSS_SPNEGO,
GSS_SPNEGO_CLIENT,
+ NTLM_SERVER_1,
NUM_HELPER_MODES
};
@@ -58,6 +59,9 @@ static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode,
static void manage_gss_spnego_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);
+
static const struct {
enum stdio_helper_mode mode;
const char *name;
@@ -69,6 +73,9 @@ static const struct {
{ 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},
+#ifdef DEVELOPER
+ { NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
+#endif
{ NUM_HELPER_MODES, NULL, NULL}
};
@@ -719,7 +726,7 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
pass=memchr(buf,' ',length);
if (!pass) {
DEBUG(2, ("Password not found. Denying access\n"));
- x_fprintf(x_stderr, "ERR\n");
+ x_fprintf(x_stdout, "ERR\n");
return;
}
*pass='\0';
@@ -1268,7 +1275,7 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper
/* 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");
@@ -1381,6 +1388,199 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper
return;
}
+static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length)
+{
+ char *request, *parameter;
+ static DATA_BLOB challenge;
+ static DATA_BLOB lm_response;
+ static DATA_BLOB nt_response;
+ static char *full_username;
+ static char *username;
+ static char *domain;
+ static char *plaintext_password;
+ static BOOL ntlm_server_1_user_session_key;
+ static BOOL ntlm_server_1_lm_session_key;
+
+ if (strequal(buf, ".")) {
+ if (!full_username && !username) {
+ x_fprintf(x_stdout, "Error: No username supplied!\n");
+ } else if (plaintext_password) {
+ /* handle this request as plaintext */
+ if (!full_username) {
+ if (asprintf(&full_username, "%s%c%s", domain, winbind_separator(), username) == -1) {
+ x_fprintf(x_stdout, "Error: Out of memory in asprintf!\n.\n");
+ return;
+ }
+ }
+ if (check_plaintext_auth(full_username, plaintext_password, False)) {
+ x_fprintf(x_stdout, "Authenticated: Yes\n");
+ } else {
+ x_fprintf(x_stdout, "Authenticated: No\n");
+ }
+ } else if (!lm_response.data || !nt_response.data) {
+ x_fprintf(x_stdout, "Error: No password supplied!\n");
+ } else if (!challenge.data) {
+ x_fprintf(x_stdout, "Error: No lanman-challenge supplied!\n");
+ } else {
+ char *error_string = NULL;
+ uchar lm_key[8];
+ uchar user_session_key[16];
+ uint32 flags = 0;
+
+ if (full_username && !username) {
+ fstring fstr_user;
+ fstring fstr_domain;
+
+ if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) {
+ /* username might be 'tainted', don't print into our new-line deleimianted stream */
+ x_fprintf(x_stdout, "Error: Could not parse into domain and username\n");
+ }
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ username = smb_xstrdup(fstr_user);
+ domain = smb_xstrdup(fstr_domain);
+ }
+
+ if (!domain) {
+ domain = smb_xstrdup(get_winbind_domain());
+ }
+
+ if (ntlm_server_1_lm_session_key)
+ flags |= WBFLAG_PAM_LMKEY;
+
+ if (ntlm_server_1_user_session_key)
+ flags |= WBFLAG_PAM_USER_SESSION_KEY;
+
+ if (!NT_STATUS_IS_OK(
+ contact_winbind_auth_crap(username,
+ domain,
+ global_myname(),
+ &challenge,
+ &lm_response,
+ &nt_response,
+ flags,
+ lm_key,
+ user_session_key,
+ &error_string,
+ NULL))) {
+
+ x_fprintf(x_stdout, "Authenticated: No\n");
+ x_fprintf(x_stdout, "Authentication-Error: %s\n.\n", error_string);
+ SAFE_FREE(error_string);
+ } else {
+ static char zeros[16];
+ char *hex_lm_key;
+ char *hex_user_session_key;
+
+ x_fprintf(x_stdout, "Authenticated: Yes\n");
+
+ if (ntlm_server_1_lm_session_key
+ && (memcmp(zeros, lm_key,
+ sizeof(lm_key)) != 0)) {
+ hex_encode((const unsigned char *)lm_key,
+ sizeof(lm_key),
+ &hex_lm_key);
+ x_fprintf(x_stdout, "LANMAN-Session-Key: %s\n", hex_lm_key);
+ SAFE_FREE(hex_lm_key);
+ }
+
+ if (ntlm_server_1_user_session_key
+ && (memcmp(zeros, user_session_key,
+ sizeof(user_session_key)) != 0)) {
+ hex_encode((const unsigned char *)user_session_key,
+ sizeof(user_session_key),
+ &hex_user_session_key);
+ x_fprintf(x_stdout, "User-Session-Key: %s\n", hex_user_session_key);
+ SAFE_FREE(hex_user_session_key);
+ }
+ }
+ }
+ /* clear out the state */
+ challenge = data_blob(NULL, 0);
+ nt_response = data_blob(NULL, 0);
+ lm_response = data_blob(NULL, 0);
+ SAFE_FREE(full_username);
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(plaintext_password);
+ ntlm_server_1_user_session_key = False;
+ ntlm_server_1_lm_session_key = False;
+ x_fprintf(x_stdout, ".\n");
+
+ return;
+ }
+
+ request = buf;
+
+ parameter = strstr_m(request, ": ");
+ if (!parameter) {
+ /* Indicates a base64 encoded structure */
+ parameter = strstr_m(request, ":: ");
+
+ if (!parameter) {
+ DEBUG(0, ("Parameter not found!\n"));
+ x_fprintf(x_stdout, "Error: Parameter not found!\n.\n");
+ return;
+ }
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+
+ base64_decode_inplace(parameter);
+ } else {
+
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+ }
+
+ if (strequal(request, "LANMAN-Challenge")) {
+ challenge = strhex_to_data_blob(parameter);
+ if (challenge.length != 8) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 8)\n.\n",
+ parameter,
+ (int)challenge.length);
+ challenge = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "NT-Response")) {
+ nt_response = strhex_to_data_blob(parameter);
+ if (nt_response.length < 24) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n",
+ parameter,
+ (int)opt_nt_response.length);
+ nt_response = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "LANMAN-Response")) {
+ lm_response = strhex_to_data_blob(parameter);
+ if (lm_response.length != 24) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 24)\n.\n",
+ parameter,
+ (int)lm_response.length);
+ lm_response = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "Password")) {
+ plaintext_password = smb_xstrdup(parameter);
+ } else if (strequal(request, "NT-Domain")) {
+ domain = smb_xstrdup(parameter);
+ } else if (strequal(request, "Username")) {
+ username = smb_xstrdup(parameter);
+ } else if (strequal(request, "Full-Username")) {
+ full_username = smb_xstrdup(parameter);
+ } else if (strequal(request, "Request-User-Session-Key")) {
+ ntlm_server_1_user_session_key = strequal(parameter, "Yes");
+ } else if (strequal(request, "Request-LanMan-Session-Key")) {
+ ntlm_server_1_lm_session_key = strequal(parameter, "Yes");
+ } else {
+ x_fprintf(x_stdout, "Error: Unknown request %s\n", request);
+ }
+ x_fprintf(x_stdout, ".\n");
+}
+
static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn)
{
char buf[SQUID_BUFFER_SIZE+1];