mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
(merge from HEAD)
NTLM Authentication:
- Add a 'privileged' mode to Winbindd. This is achieved by means of a directory
under lockdir, that the admin can change the group access for.
- This mode is now required to access with 'CRAP' authentication feature.
- This *will* break the current SQUID helper, so I've fixed up our ntlm_auth
replacement:
- Update our NTLMSSP code to cope with 'datagram' mode, where we don't get a
challenge.
- Use this to make our ntlm_auth utility suitable for use in current Squid 2.5
servers.
- Tested - works for Win2k clients, but not Win9X at present. NTLMSSP updates
are needed.
- Now uses fgets(), not x_fgets() to cope with Squid environment (I think
somthing to do with non-blocking stdin).
- Add much more robust connection code to wb_common.c - it will not connect to
a server of a different protocol version, and it will automatically try and
reconnect to the 'privileged' pipe if possible.
- This could help with 'privileged' idmap operations etc in future.
- Add a generic HEX encode routine to util_str.c,
- fix a small line of dodgy C in StrnCpy_fn()
- Correctly pull our 'session key' out of the info3 from th the DC. This is
used in both the auth code, and in for export over the winbind pipe to
ntlm_auth.
- Given the user's challenge/response and access to the privileged pipe,
allow external access to the 'session key'. To be used for MSCHAPv2
integration.
Andrew Bartlett
(This used to be commit ec071ca3dc
)
This commit is contained in:
parent
7d4bfa0eda
commit
53beee9e56
@ -350,13 +350,6 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
|
|||||||
} else {
|
} else {
|
||||||
nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str,
|
nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str,
|
||||||
user_info->smb_name.str, domain, server_info, &info3);
|
user_info->smb_name.str, domain, server_info, &info3);
|
||||||
#if 0
|
|
||||||
/* The stuff doesn't work right yet */
|
|
||||||
SMB_ASSERT(sizeof((*server_info)->session_key) == sizeof(info3.user_sess_key));
|
|
||||||
memcpy((*server_info)->session_key, info3.user_sess_key, sizeof((*server_info)->session_key)/* 16 */);
|
|
||||||
SamOEMhash((*server_info)->session_key, trust_passwd, sizeof((*server_info)->session_key));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uni_group_cache_store_netlogon(mem_ctx, &info3);
|
uni_group_cache_store_netlogon(mem_ctx, &info3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1083,6 +1083,9 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
|
|||||||
|
|
||||||
SAFE_FREE(all_group_SIDs);
|
SAFE_FREE(all_group_SIDs);
|
||||||
|
|
||||||
|
memcpy((*server_info)->session_key, info3->user_sess_key, sizeof((*server_info)->session_key)/* 16 */);
|
||||||
|
memcpy((*server_info)->first_8_lm_hash, info3->padding, 8);
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ typedef struct net_user_info_3
|
|||||||
uint32 buffer_groups; /* undocumented buffer pointer to groups. */
|
uint32 buffer_groups; /* undocumented buffer pointer to groups. */
|
||||||
uint32 user_flgs; /* user flags */
|
uint32 user_flgs; /* user flags */
|
||||||
|
|
||||||
uint8 user_sess_key[16]; /* unused user session key */
|
uint8 user_sess_key[16]; /* user session key */
|
||||||
|
|
||||||
UNIHDR hdr_logon_srv; /* logon server unicode string header */
|
UNIHDR hdr_logon_srv; /* logon server unicode string header */
|
||||||
UNIHDR hdr_logon_dom; /* logon domain unicode string header */
|
UNIHDR hdr_logon_dom; /* logon domain unicode string header */
|
||||||
|
@ -603,8 +603,12 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
|
|||||||
*dest = 0;
|
*dest = 0;
|
||||||
return(dest);
|
return(dest);
|
||||||
}
|
}
|
||||||
while (n-- && (*d++ = *src++))
|
|
||||||
;
|
while (n-- && (*d = *src)) {
|
||||||
|
d++;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
*d = 0;
|
*d = 0;
|
||||||
return(dest);
|
return(dest);
|
||||||
}
|
}
|
||||||
@ -681,6 +685,22 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex)
|
|||||||
return num_chars;
|
return num_chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine to print a buffer as HEX digits, into an allocated string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *hex_buffer;
|
||||||
|
|
||||||
|
*out_hex_buffer = smb_xmalloc((len*2)+1);
|
||||||
|
hex_buffer = *out_hex_buffer;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if a string is part of a list.
|
Check if a string is part of a list.
|
||||||
**/
|
**/
|
||||||
|
@ -121,7 +121,8 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
|
|||||||
{
|
{
|
||||||
DATA_BLOB struct_blob;
|
DATA_BLOB struct_blob;
|
||||||
fstring dnsname, dnsdomname;
|
fstring dnsname, dnsdomname;
|
||||||
uint32 ntlmssp_command, neg_flags, chal_flags;
|
uint32 neg_flags = 0;
|
||||||
|
uint32 ntlmssp_command, chal_flags;
|
||||||
char *cliname=NULL, *domname=NULL;
|
char *cliname=NULL, *domname=NULL;
|
||||||
const uint8 *cryptkey;
|
const uint8 *cryptkey;
|
||||||
const char *target_name;
|
const char *target_name;
|
||||||
@ -131,20 +132,24 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
|
|||||||
file_save("ntlmssp_negotiate.dat", request.data, request.length);
|
file_save("ntlmssp_negotiate.dat", request.data, request.length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!msrpc_parse(&request, "CddAA",
|
if (request.length) {
|
||||||
"NTLMSSP",
|
if (!msrpc_parse(&request, "CddAA",
|
||||||
&ntlmssp_command,
|
"NTLMSSP",
|
||||||
&neg_flags,
|
&ntlmssp_command,
|
||||||
&cliname,
|
&neg_flags,
|
||||||
&domname)) {
|
&cliname,
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
&domname)) {
|
||||||
|
DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
|
||||||
|
dump_data(2, request.data, request.length);
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_FREE(cliname);
|
||||||
|
SAFE_FREE(domname);
|
||||||
|
|
||||||
|
debug_ntlmssp_flags(neg_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFE_FREE(cliname);
|
|
||||||
SAFE_FREE(domname);
|
|
||||||
|
|
||||||
debug_ntlmssp_flags(neg_flags);
|
|
||||||
|
|
||||||
cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
|
cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
|
||||||
|
|
||||||
data_blob_free(&ntlmssp_state->chal);
|
data_blob_free(&ntlmssp_state->chal);
|
||||||
@ -268,6 +273,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
|
|||||||
&ntlmssp_state->workstation,
|
&ntlmssp_state->workstation,
|
||||||
&sess_key,
|
&sess_key,
|
||||||
&neg_flags)) {
|
&neg_flags)) {
|
||||||
|
DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
|
||||||
|
dump_data(2, request.data, request.length);
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,13 +364,19 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state,
|
|||||||
uint32 ntlmssp_command;
|
uint32 ntlmssp_command;
|
||||||
*reply = data_blob(NULL, 0);
|
*reply = data_blob(NULL, 0);
|
||||||
|
|
||||||
if (!msrpc_parse(&request, "Cd",
|
if (request.length) {
|
||||||
"NTLMSSP",
|
if (!msrpc_parse(&request, "Cd",
|
||||||
&ntlmssp_command)) {
|
"NTLMSSP",
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
&ntlmssp_command)) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* 'datagram' mode - no neg packet */
|
||||||
|
ntlmssp_command = NTLMSSP_NEGOTIATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntlmssp_command != ntlmssp_state->expected_state) {
|
if (ntlmssp_command != ntlmssp_state->expected_state) {
|
||||||
|
DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,6 +385,7 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state,
|
|||||||
} else if (ntlmssp_command == NTLMSSP_AUTH) {
|
} else if (ntlmssp_command == NTLMSSP_AUTH) {
|
||||||
return ntlmssp_server_auth(ntlmssp_state, request, reply);
|
return ntlmssp_server_auth(ntlmssp_state, request, reply);
|
||||||
} else {
|
} else {
|
||||||
|
DEBUG(1, ("unknown NTLMSSP command %u\n", ntlmssp_command, ntlmssp_state->expected_state));
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,27 +131,16 @@ static int make_safe_fd(int fd)
|
|||||||
|
|
||||||
/* Connect to winbindd socket */
|
/* Connect to winbindd socket */
|
||||||
|
|
||||||
int winbind_open_pipe_sock(void)
|
static int winbind_named_pipe_sock(const char *dir)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_UNIXSOCKET
|
|
||||||
struct sockaddr_un sunaddr;
|
struct sockaddr_un sunaddr;
|
||||||
static pid_t our_pid;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
pstring path;
|
pstring path;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (our_pid != getpid()) {
|
|
||||||
close_sock();
|
|
||||||
our_pid = getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (winbindd_fd != -1) {
|
|
||||||
return winbindd_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check permissions on unix socket directory */
|
/* Check permissions on unix socket directory */
|
||||||
|
|
||||||
if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) {
|
if (lstat(dir, &st) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,13 +151,13 @@ int winbind_open_pipe_sock(void)
|
|||||||
|
|
||||||
/* Connect to socket */
|
/* Connect to socket */
|
||||||
|
|
||||||
strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1);
|
strncpy(path, dir, sizeof(path) - 1);
|
||||||
path[sizeof(path) - 1] = '\0';
|
path[sizeof(path) - 1] = '\0';
|
||||||
|
|
||||||
strncat(path, "/", sizeof(path) - 1);
|
strncat(path, "/", sizeof(path) - 1 - strlen(path));
|
||||||
path[sizeof(path) - 1] = '\0';
|
path[sizeof(path) - 1] = '\0';
|
||||||
|
|
||||||
strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1);
|
strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1 - strlen(path));
|
||||||
path[sizeof(path) - 1] = '\0';
|
path[sizeof(path) - 1] = '\0';
|
||||||
|
|
||||||
ZERO_STRUCT(sunaddr);
|
ZERO_STRUCT(sunaddr);
|
||||||
@ -196,16 +185,60 @@ int winbind_open_pipe_sock(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((winbindd_fd = make_safe_fd( fd)) == -1) {
|
if ((fd = make_safe_fd( fd)) == -1) {
|
||||||
return winbindd_fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
|
if (connect(fd, (struct sockaddr *)&sunaddr,
|
||||||
sizeof(sunaddr)) == -1) {
|
sizeof(sunaddr)) == -1) {
|
||||||
close_sock();
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect to winbindd socket */
|
||||||
|
|
||||||
|
int winbind_open_pipe_sock(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_UNIXSOCKET
|
||||||
|
static pid_t our_pid;
|
||||||
|
struct winbindd_request request;
|
||||||
|
struct winbindd_response response;
|
||||||
|
ZERO_STRUCT(request);
|
||||||
|
ZERO_STRUCT(response);
|
||||||
|
|
||||||
|
if (our_pid != getpid()) {
|
||||||
|
close_sock();
|
||||||
|
our_pid = getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winbindd_fd != -1) {
|
||||||
|
return winbindd_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((winbindd_fd = winbind_named_pipe_sock(WINBINDD_SOCKET_DIR)) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* version-check the socket */
|
||||||
|
|
||||||
|
if ((winbindd_request(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) {
|
||||||
|
close_sock();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try and get priv pipe */
|
||||||
|
|
||||||
|
if (winbindd_request(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) {
|
||||||
|
int fd;
|
||||||
|
if ((fd = winbind_named_pipe_sock(response.extra_data)) != -1) {
|
||||||
|
close(winbindd_fd);
|
||||||
|
winbindd_fd = fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return winbindd_fd;
|
return winbindd_fd;
|
||||||
#else
|
#else
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -265,6 +265,7 @@ static struct dispatch_table dispatch_table[] = {
|
|||||||
{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
|
{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
|
||||||
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
|
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
|
||||||
{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
|
{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
|
||||||
|
{ WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir, "WINBINDD_PRIV_PIPE_DIR" },
|
||||||
|
|
||||||
/* WINS functions */
|
/* WINS functions */
|
||||||
|
|
||||||
@ -311,7 +312,7 @@ static void process_request(struct winbindd_cli_state *state)
|
|||||||
|
|
||||||
/* Process a new connection by adding it to the client connection list */
|
/* Process a new connection by adding it to the client connection list */
|
||||||
|
|
||||||
static void new_connection(int listen_sock)
|
static void new_connection(int listen_sock, BOOL privilaged)
|
||||||
{
|
{
|
||||||
struct sockaddr_un sunaddr;
|
struct sockaddr_un sunaddr;
|
||||||
struct winbindd_cli_state *state;
|
struct winbindd_cli_state *state;
|
||||||
@ -342,6 +343,8 @@ static void new_connection(int listen_sock)
|
|||||||
|
|
||||||
state->last_access = time(NULL);
|
state->last_access = time(NULL);
|
||||||
|
|
||||||
|
state->privilaged = privilaged;
|
||||||
|
|
||||||
/* Add to connection list */
|
/* Add to connection list */
|
||||||
|
|
||||||
winbindd_add_client(state);
|
winbindd_add_client(state);
|
||||||
@ -553,7 +556,7 @@ static void process_loop(void)
|
|||||||
while (1) {
|
while (1) {
|
||||||
struct winbindd_cli_state *state;
|
struct winbindd_cli_state *state;
|
||||||
fd_set r_fds, w_fds;
|
fd_set r_fds, w_fds;
|
||||||
int maxfd, listen_sock, selret;
|
int maxfd, listen_sock, listen_priv_sock, selret;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
|
|
||||||
/* Handle messages */
|
/* Handle messages */
|
||||||
@ -572,17 +575,19 @@ static void process_loop(void)
|
|||||||
/* Initialise fd lists for select() */
|
/* Initialise fd lists for select() */
|
||||||
|
|
||||||
listen_sock = open_winbindd_socket();
|
listen_sock = open_winbindd_socket();
|
||||||
|
listen_priv_sock = open_winbindd_priv_socket();
|
||||||
|
|
||||||
if (listen_sock == -1) {
|
if (listen_sock == -1 || listen_priv_sock == -1) {
|
||||||
perror("open_winbind_socket");
|
perror("open_winbind_socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxfd = listen_sock;
|
maxfd = MAX(listen_sock, listen_priv_sock);
|
||||||
|
|
||||||
FD_ZERO(&r_fds);
|
FD_ZERO(&r_fds);
|
||||||
FD_ZERO(&w_fds);
|
FD_ZERO(&w_fds);
|
||||||
FD_SET(listen_sock, &r_fds);
|
FD_SET(listen_sock, &r_fds);
|
||||||
|
FD_SET(listen_priv_sock, &r_fds);
|
||||||
|
|
||||||
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
|
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
@ -659,7 +664,22 @@ static void process_loop(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_connection(listen_sock);
|
/* new, non-privilaged connection */
|
||||||
|
new_connection(listen_sock, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(listen_priv_sock, &r_fds)) {
|
||||||
|
while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
|
||||||
|
DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n",
|
||||||
|
WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
|
||||||
|
if (!remove_idle_client()) {
|
||||||
|
DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n",
|
||||||
|
WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* new, privilaged connection */
|
||||||
|
new_connection(listen_priv_sock, True);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process activity on client connections */
|
/* Process activity on client connections */
|
||||||
|
@ -42,6 +42,8 @@ struct winbindd_cli_state {
|
|||||||
BOOL finished; /* Can delete from list */
|
BOOL finished; /* Can delete from list */
|
||||||
BOOL write_extra_data; /* Write extra_data field */
|
BOOL write_extra_data; /* Write extra_data field */
|
||||||
time_t last_access; /* Time of last access (read or write) */
|
time_t last_access; /* Time of last access (read or write) */
|
||||||
|
BOOL privilaged; /* Is the client 'privilaged' */
|
||||||
|
|
||||||
struct winbindd_request request; /* Request from client */
|
struct winbindd_request request; /* Request from client */
|
||||||
struct winbindd_response response; /* Respose to client */
|
struct winbindd_response response; /* Respose to client */
|
||||||
struct getent_state *getpwent_state; /* State for getpwent() */
|
struct getent_state *getpwent_state; /* State for getpwent() */
|
||||||
|
@ -233,3 +233,20 @@ enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state)
|
|||||||
|
|
||||||
return WINBINDD_OK;
|
return WINBINDD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* What's my name again? */
|
||||||
|
|
||||||
|
enum winbindd_result winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
DEBUG(3, ("[%5d]: request location of privilaged pipe\n", state->pid));
|
||||||
|
|
||||||
|
state->response.extra_data = strdup(get_winbind_priv_pipe_dir());
|
||||||
|
if (!state->response.extra_data)
|
||||||
|
return WINBINDD_ERROR;
|
||||||
|
|
||||||
|
/* must add one to length to copy the 0 for string termination */
|
||||||
|
state->response.length += strlen((char *)state->response.extra_data) + 1;
|
||||||
|
|
||||||
|
return WINBINDD_OK;
|
||||||
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */
|
#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */
|
||||||
#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */
|
#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */
|
||||||
|
#define WINBINDD_PRIV_SOCKET_SUBDIR "winbindd_privilaged" /* name of subdirectory of lp_lockdir() to hold the 'privilaged' pipe */
|
||||||
#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */
|
#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */
|
||||||
#define WINBINDD_DONT_ENV "_NO_WINBINDD"
|
#define WINBINDD_DONT_ENV "_NO_WINBINDD"
|
||||||
|
|
||||||
@ -105,6 +105,9 @@ enum winbindd_cmd {
|
|||||||
WINBINDD_NETBIOS_NAME, /* The netbios name of the server */
|
WINBINDD_NETBIOS_NAME, /* The netbios name of the server */
|
||||||
/* Placeholder for end of cmd list */
|
/* Placeholder for end of cmd list */
|
||||||
|
|
||||||
|
/* find the location of our privilaged pipe */
|
||||||
|
WINBINDD_PRIV_PIPE_DIR,
|
||||||
|
|
||||||
WINBINDD_NUM_CMDS
|
WINBINDD_NUM_CMDS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,6 +174,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
|||||||
|
|
||||||
DATA_BLOB lm_resp, nt_resp;
|
DATA_BLOB lm_resp, nt_resp;
|
||||||
|
|
||||||
|
if (!state->privilaged) {
|
||||||
|
DEBUG(2, ("winbindd_pam_auth_crap: non-privilaged access denied!\n"));
|
||||||
|
result = NT_STATUS_ACCESS_DENIED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure null termination */
|
/* Ensure null termination */
|
||||||
state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0';
|
state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0';
|
||||||
|
|
||||||
@ -272,19 +278,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
|||||||
result = append_info3_as_ndr(mem_ctx, state, &info3);
|
result = append_info3_as_ndr(mem_ctx, state, &info3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* we don't currently do this stuff right */
|
|
||||||
/* Doing an assert in a daemon is going to be a pretty bad
|
|
||||||
idea. - tpot */
|
|
||||||
if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
|
if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
|
||||||
SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key));
|
|
||||||
memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
|
memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
|
||||||
}
|
}
|
||||||
if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) {
|
if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) {
|
||||||
SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key));
|
|
||||||
memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
|
memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -444,9 +444,15 @@ void fill_domain_username(fstring name, const char *domain, const char *user)
|
|||||||
* Winbindd socket accessor functions
|
* Winbindd socket accessor functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
char *get_winbind_priv_pipe_dir(void)
|
||||||
|
{
|
||||||
|
return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the winbindd socket */
|
/* Open the winbindd socket */
|
||||||
|
|
||||||
static int _winbindd_socket = -1;
|
static int _winbindd_socket = -1;
|
||||||
|
static int _winbindd_priv_socket = -1;
|
||||||
|
|
||||||
int open_winbindd_socket(void)
|
int open_winbindd_socket(void)
|
||||||
{
|
{
|
||||||
@ -460,6 +466,18 @@ int open_winbindd_socket(void)
|
|||||||
return _winbindd_socket;
|
return _winbindd_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int open_winbindd_priv_socket(void)
|
||||||
|
{
|
||||||
|
if (_winbindd_priv_socket == -1) {
|
||||||
|
_winbindd_priv_socket = create_pipe_sock(
|
||||||
|
get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
|
||||||
|
DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
|
||||||
|
_winbindd_priv_socket));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _winbindd_priv_socket;
|
||||||
|
}
|
||||||
|
|
||||||
/* Close the winbindd socket */
|
/* Close the winbindd socket */
|
||||||
|
|
||||||
void close_winbindd_socket(void)
|
void close_winbindd_socket(void)
|
||||||
@ -470,6 +488,12 @@ void close_winbindd_socket(void)
|
|||||||
close(_winbindd_socket);
|
close(_winbindd_socket);
|
||||||
_winbindd_socket = -1;
|
_winbindd_socket = -1;
|
||||||
}
|
}
|
||||||
|
if (_winbindd_priv_socket != -1) {
|
||||||
|
DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
|
||||||
|
_winbindd_priv_socket));
|
||||||
|
close(_winbindd_priv_socket);
|
||||||
|
_winbindd_priv_socket = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -597,7 +597,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|||||||
|
|
||||||
NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
||||||
const char *username, const char *domain, const char *workstation,
|
const char *username, const char *domain, const char *workstation,
|
||||||
const uint8 chal[8],
|
const uint8 chal[8],
|
||||||
DATA_BLOB lm_response, DATA_BLOB nt_response,
|
DATA_BLOB lm_response, DATA_BLOB nt_response,
|
||||||
NET_USER_INFO_3 *info3)
|
NET_USER_INFO_3 *info3)
|
||||||
|
|
||||||
@ -610,6 +610,8 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c
|
|||||||
NET_ID_INFO_CTR ctr;
|
NET_ID_INFO_CTR ctr;
|
||||||
int validation_level = 3;
|
int validation_level = 3;
|
||||||
char *workstation_name_slash;
|
char *workstation_name_slash;
|
||||||
|
uint8 netlogon_sess_key[16];
|
||||||
|
static uint8 zeros[16];
|
||||||
|
|
||||||
ZERO_STRUCT(q);
|
ZERO_STRUCT(q);
|
||||||
ZERO_STRUCT(r);
|
ZERO_STRUCT(r);
|
||||||
@ -662,6 +664,15 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZERO_STRUCT(netlogon_sess_key);
|
||||||
|
memcpy(netlogon_sess_key, cli->sess_key, 8);
|
||||||
|
|
||||||
|
if (memcmp(zeros, info3->user_sess_key, 16) != 0)
|
||||||
|
SamOEMhash(info3->user_sess_key, netlogon_sess_key, 16);
|
||||||
|
|
||||||
|
if (memcmp(zeros, info3->padding, 16) != 0)
|
||||||
|
SamOEMhash(info3->padding, netlogon_sess_key, 16);
|
||||||
|
|
||||||
/* Return results */
|
/* Return results */
|
||||||
|
|
||||||
result = r.status;
|
result = r.status;
|
||||||
|
@ -51,6 +51,8 @@ static unsigned char *lm_response;
|
|||||||
static size_t lm_response_len;
|
static size_t lm_response_len;
|
||||||
static unsigned char *nt_response;
|
static unsigned char *nt_response;
|
||||||
static size_t nt_response_len;
|
static size_t nt_response_len;
|
||||||
|
static int request_lm_key;
|
||||||
|
static int request_nt_key;
|
||||||
|
|
||||||
static char *password;
|
static char *password;
|
||||||
|
|
||||||
@ -197,7 +199,7 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state)
|
|||||||
memcpy(request.data.auth_crap.lm_resp, ntlmssp_state->lm_resp.data,
|
memcpy(request.data.auth_crap.lm_resp, ntlmssp_state->lm_resp.data,
|
||||||
MIN(ntlmssp_state->lm_resp.length, sizeof(request.data.auth_crap.lm_resp)));
|
MIN(ntlmssp_state->lm_resp.length, sizeof(request.data.auth_crap.lm_resp)));
|
||||||
|
|
||||||
memcpy(request.data.auth_crap.nt_resp, ntlmssp_state->lm_resp.data,
|
memcpy(request.data.auth_crap.nt_resp, ntlmssp_state->nt_resp.data,
|
||||||
MIN(ntlmssp_state->nt_resp.length, sizeof(request.data.auth_crap.nt_resp)));
|
MIN(ntlmssp_state->nt_resp.length, sizeof(request.data.auth_crap.nt_resp)));
|
||||||
|
|
||||||
request.data.auth_crap.lm_resp_len = ntlmssp_state->lm_resp.length;
|
request.data.auth_crap.lm_resp_len = ntlmssp_state->lm_resp.length;
|
||||||
@ -217,10 +219,28 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state)
|
|||||||
static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
|
static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
|
||||||
char *buf, int length)
|
char *buf, int length)
|
||||||
{
|
{
|
||||||
static NTLMSSP_STATE *ntlmssp_state;
|
static NTLMSSP_STATE *ntlmssp_state = NULL;
|
||||||
DATA_BLOB request, reply;
|
DATA_BLOB request, reply;
|
||||||
NTSTATUS nt_status;
|
NTSTATUS nt_status;
|
||||||
|
|
||||||
|
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 if (strcmp(buf, "YR") == 0) {
|
||||||
|
request = data_blob(NULL, 0);
|
||||||
|
if (ntlmssp_state)
|
||||||
|
ntlmssp_server_end(&ntlmssp_state);
|
||||||
|
} else {
|
||||||
|
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
|
||||||
|
x_fprintf(x_stdout, "BH\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ntlmssp_state) {
|
if (!ntlmssp_state) {
|
||||||
ntlmssp_server_start(&ntlmssp_state);
|
ntlmssp_server_start(&ntlmssp_state);
|
||||||
ntlmssp_state->check_password = winbind_pw_check;
|
ntlmssp_state->check_password = winbind_pw_check;
|
||||||
@ -228,15 +248,8 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
|
|||||||
ntlmssp_state->get_global_myname = get_winbind_netbios_name;
|
ntlmssp_state->get_global_myname = get_winbind_netbios_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(buf) < 3) {
|
DEBUG(10, ("got NTLMSSP packet:\n"));
|
||||||
x_fprintf(x_stdout, "BH\n");
|
dump_data(10, request.data, request.length);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
request = base64_decode_data_blob(buf + 3);
|
|
||||||
|
|
||||||
DEBUG(0, ("got NTLMSSP packet:\n"));
|
|
||||||
dump_data(0, request.data, request.length);
|
|
||||||
|
|
||||||
nt_status = ntlmssp_server_update(ntlmssp_state, request, &reply);
|
nt_status = ntlmssp_server_update(ntlmssp_state, request, &reply);
|
||||||
|
|
||||||
@ -245,10 +258,13 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
|
|||||||
x_fprintf(x_stdout, "TT %s\n", reply_base64);
|
x_fprintf(x_stdout, "TT %s\n", reply_base64);
|
||||||
SAFE_FREE(reply_base64);
|
SAFE_FREE(reply_base64);
|
||||||
data_blob_free(&reply);
|
data_blob_free(&reply);
|
||||||
|
DEBUG(10, ("NTLMSSP challenge\n"));
|
||||||
} else if (!NT_STATUS_IS_OK(nt_status)) {
|
} else if (!NT_STATUS_IS_OK(nt_status)) {
|
||||||
x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status));
|
x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status));
|
||||||
|
DEBUG(10, ("NTLMSSP %s\n", nt_errstr(nt_status)));
|
||||||
} else {
|
} else {
|
||||||
x_fprintf(x_stdout, "AF %s\\%s\n", ntlmssp_state->domain, ntlmssp_state->user);
|
x_fprintf(x_stdout, "AF %s\\%s\n", ntlmssp_state->domain, ntlmssp_state->user);
|
||||||
|
DEBUG(10, ("NTLMSSP OK!\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
data_blob_free(&request);
|
data_blob_free(&request);
|
||||||
@ -287,10 +303,11 @@ static void manage_squid_request(enum squid_mode squid_mode)
|
|||||||
int length;
|
int length;
|
||||||
char *c;
|
char *c;
|
||||||
static BOOL err;
|
static BOOL err;
|
||||||
|
|
||||||
if (x_fgets(buf, sizeof(buf)-1, x_stdin) == NULL) {
|
/* this is not a typo - x_fgets doesn't work too well under squid */
|
||||||
DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", errno,
|
if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
|
||||||
strerror(errno)));
|
DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", ferror(stdin),
|
||||||
|
strerror(ferror(stdin))));
|
||||||
exit(1); /* BIIG buffer */
|
exit(1); /* BIIG buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,12 +358,22 @@ static BOOL check_auth_crap(void)
|
|||||||
{
|
{
|
||||||
struct winbindd_request request;
|
struct winbindd_request request;
|
||||||
struct winbindd_response response;
|
struct winbindd_response response;
|
||||||
|
char *lm_key;
|
||||||
|
char *nt_key;
|
||||||
|
static uint8 zeros[16];
|
||||||
|
|
||||||
NSS_STATUS result;
|
NSS_STATUS result;
|
||||||
/* Send off request */
|
/* Send off request */
|
||||||
|
|
||||||
ZERO_STRUCT(request);
|
ZERO_STRUCT(request);
|
||||||
ZERO_STRUCT(response);
|
ZERO_STRUCT(response);
|
||||||
|
|
||||||
|
if (request_lm_key)
|
||||||
|
request.data.auth_crap.flags |= WINBIND_PAM_LMKEY;
|
||||||
|
|
||||||
|
if (request_nt_key)
|
||||||
|
request.data.auth_crap.flags |= WINBIND_PAM_NTKEY;
|
||||||
|
|
||||||
fstrcpy(request.data.auth_crap.user, username);
|
fstrcpy(request.data.auth_crap.user, username);
|
||||||
|
|
||||||
fstrcpy(request.data.auth_crap.domain, domain);
|
fstrcpy(request.data.auth_crap.domain, domain);
|
||||||
@ -373,6 +400,27 @@ static BOOL check_auth_crap(void)
|
|||||||
response.data.auth.nt_status_string,
|
response.data.auth.nt_status_string,
|
||||||
response.data.auth.nt_status);
|
response.data.auth.nt_status);
|
||||||
|
|
||||||
|
if (response.data.auth.nt_status == 0) {
|
||||||
|
if (request_lm_key
|
||||||
|
&& (memcmp(zeros, response.data.auth.first_8_lm_hash,
|
||||||
|
sizeof(response.data.auth.first_8_lm_hash)) != 0)) {
|
||||||
|
hex_encode(response.data.auth.first_8_lm_hash,
|
||||||
|
sizeof(response.data.auth.first_8_lm_hash),
|
||||||
|
&lm_key);
|
||||||
|
d_printf("LM_KEY: %s\n", lm_key);
|
||||||
|
SAFE_FREE(lm_key);
|
||||||
|
}
|
||||||
|
if (request_nt_key
|
||||||
|
&& (memcmp(zeros, response.data.auth.nt_session_key,
|
||||||
|
sizeof(response.data.auth.nt_session_key)) != 0)) {
|
||||||
|
hex_encode(response.data.auth.nt_session_key,
|
||||||
|
sizeof(response.data.auth.nt_session_key),
|
||||||
|
&nt_key);
|
||||||
|
d_printf("NT_KEY: %s\n", nt_key);
|
||||||
|
SAFE_FREE(nt_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result == NSS_STATUS_SUCCESS;
|
return result == NSS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,68 +434,11 @@ enum {
|
|||||||
OPT_RESPONSE,
|
OPT_RESPONSE,
|
||||||
OPT_LM,
|
OPT_LM,
|
||||||
OPT_NT,
|
OPT_NT,
|
||||||
OPT_PASSWORD
|
OPT_PASSWORD,
|
||||||
|
OPT_LM_KEY,
|
||||||
|
OPT_NT_KEY
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Routine to set hex password characters into an allocated array.
|
|
||||||
**************************************************************/
|
|
||||||
|
|
||||||
static void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *hex_buffer;
|
|
||||||
|
|
||||||
*out_hex_buffer = smb_xmalloc((len*2)+1);
|
|
||||||
hex_buffer = *out_hex_buffer;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Routine to get the 32 hex characters and turn them
|
|
||||||
into a 16 byte array.
|
|
||||||
**************************************************************/
|
|
||||||
|
|
||||||
static BOOL hex_decode(const char *hex_buf_in, unsigned char **out_buffer, size_t *size)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
size_t hex_buf_in_len = strlen(hex_buf_in);
|
|
||||||
unsigned char partial_byte_hex;
|
|
||||||
unsigned char partial_byte;
|
|
||||||
const char *hexchars = "0123456789ABCDEF";
|
|
||||||
char *p;
|
|
||||||
BOOL high = True;
|
|
||||||
|
|
||||||
if (!hex_buf_in)
|
|
||||||
return (False);
|
|
||||||
|
|
||||||
*size = (hex_buf_in_len + 1) / 2;
|
|
||||||
|
|
||||||
*out_buffer = smb_xmalloc(*size);
|
|
||||||
|
|
||||||
for (i = 0; i < hex_buf_in_len; i++) {
|
|
||||||
partial_byte_hex = toupper(hex_buf_in[i]);
|
|
||||||
|
|
||||||
p = strchr(hexchars, partial_byte_hex);
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
return (False);
|
|
||||||
|
|
||||||
partial_byte = PTR_DIFF(p, hexchars);
|
|
||||||
|
|
||||||
if (high) {
|
|
||||||
(*out_buffer)[i / 2] = (partial_byte << 4);
|
|
||||||
} else {
|
|
||||||
(*out_buffer)[i / 2] |= partial_byte;
|
|
||||||
}
|
|
||||||
high = !high;
|
|
||||||
}
|
|
||||||
return (True);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
@ -464,6 +455,8 @@ int main(int argc, const char **argv)
|
|||||||
{ "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"},
|
{ "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"},
|
||||||
{ "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"},
|
{ "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"},
|
||||||
{ "password", 0, POPT_ARG_STRING, &password, OPT_PASSWORD, "User's plaintext password"},
|
{ "password", 0, POPT_ARG_STRING, &password, OPT_PASSWORD, "User's plaintext password"},
|
||||||
|
{ "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retreive LM session key"},
|
||||||
|
{ "request-nt-key", 0, POPT_ARG_NONE, &request_nt_key, OPT_NT_KEY, "Retreive NT session key"},
|
||||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
|
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
|
||||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
|
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
|
||||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
|
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
|
||||||
@ -491,20 +484,27 @@ int main(int argc, const char **argv)
|
|||||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case OPT_CHALLENGE:
|
case OPT_CHALLENGE:
|
||||||
if (!hex_decode(hex_challenge, &challenge, &challenge_len)) {
|
challenge_len = strlen(hex_challenge);
|
||||||
fprintf(stderr, "hex decode of %s failed!\n", hex_challenge);
|
challenge = smb_xmalloc((challenge_len+1)/2);
|
||||||
|
if ((challenge_len = strhex_to_str(challenge, challenge_len, hex_challenge)) != 8) {
|
||||||
|
fprintf(stderr, "hex decode of %s failed (only got %u bytes)!\n",
|
||||||
|
hex_challenge, challenge_len);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_LM:
|
case OPT_LM:
|
||||||
if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) {
|
lm_response_len = strlen(hex_lm_response);
|
||||||
fprintf(stderr, "hex decode of %s failed!\n", lm_response);
|
lm_response = smb_xmalloc((lm_response_len+1)/2);
|
||||||
|
if ((lm_response_len = strhex_to_str(lm_response, lm_response_len, hex_lm_response)) != 24) {
|
||||||
|
fprintf(stderr, "hex decode of %s failed!\n", hex_lm_response);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_NT:
|
case OPT_NT:
|
||||||
if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) {
|
nt_response_len = strlen(hex_nt_response);
|
||||||
fprintf(stderr, "hex decode of %s failed!\n", lm_response);
|
nt_response = smb_xmalloc((nt_response_len+1)/2);
|
||||||
|
if ((nt_response_len = strhex_to_str(nt_response, nt_response_len, hex_nt_response)) < 24) {
|
||||||
|
fprintf(stderr, "hex decode of %s failed!\n", hex_nt_response);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user