&info3);
if (NT_STATUS_IS_OK(nt_status)) {
- (*server_info)->was_mapped |= user_info->was_mapped;
+ if (user_info->was_mapped) {
+ (*server_info)->was_mapped = user_info->was_mapped;
+ }
if ( ! (*server_info)->guest) {
/* if a real user check pam account restrictions */
}
if (NT_STATUS_IS_OK(nt_status)) {
- (*server_info)->was_mapped |= user_info->was_mapped;
+ if (user_info->was_mapped) {
+ (*server_info)->was_mapped = user_info->was_mapped;
+ }
}
}
} else if (NT_STATUS_IS_OK(nt_status)) {
d_printf("iosize <n> or iosize 0x<n>. "
"(Encrypted connection) ,"
"Minimum is 16384 (0x4000), "
- "max is 64512 (0xFC00)\n");
+ "max is 130048 (0x1FC00)\n");
}
return 1;
}
if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
d_printf("iosize out of range for encrypted "
"connection (min = 16384 (0x4000), "
- "max = 64512 (0xFC00)");
+ "max = 130048 (0x1FC00)");
return 1;
} else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
d_printf("iosize out of range (min = 16384 (0x4000), "
timeout.tv_usec = 0;
sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
- /* We deliberately use receive_smb instead of
+ /* We deliberately use receive_smb_raw instead of
client_receive_smb as we want to receive
session keepalives and then drop them here.
*/
if (FD_ISSET(cli->fd,&fds)) {
- if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
+ if (receive_smb_raw(cli->fd,cli->inbuf,0,0,&cli->smb_rw_error) == -1) {
DEBUG(0, ("Read from server failed, maybe it closed the "
"connection\n"));
return;
}
+ if(CVAL(cli->inbuf,0) != SMBkeepalive) {
+ DEBUG(0, ("Read from server "
+ "returned unexpected packet!\n"));
+ return;
+ }
+
goto again;
}
{ "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
{ "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
{ "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
- { "encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
calling_name = talloc_strdup(frame, global_myname() );
}
+ smb_encrypt = get_cmdline_auth_info_smb_encrypt();
init_names();
if(new_name_resolve_order)
static struct cli_state *smb_connect(const char *, const char *, int, const char *, const char *, const char *, const char *);
static int smb_print(struct cli_state *, char *, FILE *);
static char * uri_unescape_alloc(const char *);
-
+#if 0
+static bool smb_encrypt;
+#endif
/*
* 'main()' - Main entry for SMB backend.
return NULL;
}
+#if 0
+ /* Need to work out how to specify this on the URL. */
+ if (smb_encrypt)
+ {
+ if (!cli_cm_force_encryption(cli,
+ username,
+ password,
+ workgroup,
+ share))
+ {
+ fprintf(stderr, "ERROR: encryption setup failed\n");
+ cli_shutdown(cli);
+ return NULL;
+ }
+ }
+#endif
+
return cli;
}
* and retrieved with smbc_option_set() and smbc_option_get().
*/
void * _user_data;
+
+ /*
+ * Should we attempt UNIX smb encryption ?
+ * Set to 0 if we should never attempt, set to 1 if
+ * encryption requested, set to 2 if encryption required.
+ */
+ int _smb_encryption_level;
};
bool got_pass;
bool use_kerberos;
int signing_state;
+ bool smb_encrypt;
};
#endif /* _POPT_COMMON_H */
int num_files_open;
unsigned int num_smb_operations; /* Count of smb operations on this tree. */
int encrypt_level;
+ bool encrypted_tid;
/* Semantics requested by the client or forced by the server config. */
bool case_sensitive;
const uint8 *inbuf;
uint8 *outbuf;
size_t unread_bytes;
+ bool encrypted;
+ connection_struct *conn;
};
/* Defines for the sent_oplock_break field above. */
struct pending_message_list *next, *prev;
struct timeval request_time; /* When was this first issued? */
struct timeval end_time; /* When does this time out? */
+ bool encrypted;
DATA_BLOB buf;
DATA_BLOB private_data;
};
#define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx)))
#define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx)))
-#define ERROR_DOS(class,code) error_packet(inbuf,outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
-#define ERROR_NT(status) error_packet(inbuf,outbuf,0,0,status,__LINE__,__FILE__)
-#define ERROR_FORCE_NT(status) error_packet(inbuf,outbuf,-1,-1,status,__LINE__,__FILE__)
-#define ERROR_BOTH(status,class,code) error_packet(inbuf,outbuf,class,code,status,__LINE__,__FILE__)
+#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
+#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__)
+#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__)
+#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__)
#define reply_nterror(req,status) reply_nt_error(req,status,__LINE__,__FILE__)
#define reply_force_nterror(req,status) reply_force_nt_error(req,status,__LINE__,__FILE__)
#define _smb_setlen_large(buf,len) do { buf[0] = 0; buf[1] = ((len)&0xFF0000)>>16; \
buf[2] = ((len)&0xFF00)>>8; buf[3] = (len)&0xFF; } while (0)
+#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == Required) : false)
+#define IS_CONN_ENCRYPTED(conn) ((conn) ? (conn)->encrypted_tid : false)
+
/*******************************************************************
find the difference in milliseconds between two struct timeval
values
{
return NT_STATUS_OK;
}
-
-NTSTATUS srv_decrypt_buffer(char *buf)
-{
- return NT_STATUS_OK;
-}
-
-NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out)
-{
- *buf_out = buffer;
- return NT_STATUS_OK;
-}
-
-void srv_free_enc_buffer(char *buf)
-{
- ;
-}
-
-bool srv_encryption_on(void)
-{
- return false;
-}
/*
* Unix SMB/CIFS implementation.
* Join Support (gtk + netapi)
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
+#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
SAFE_FREE(s->my_fqdn);
SAFE_FREE(s->my_dnsdomain);
SAFE_FREE(s->my_hostname);
-
}
static void do_cleanup(struct join_state *state)
gtk_widget_destroy(dialog);
#endif
- gtk_label_set_text(GTK_LABEL(state->label_reboot), "Changes will take effect after you restart this computer");
+ gtk_label_set_text(GTK_LABEL(state->label_reboot),
+ "Changes will take effect after you restart this computer");
debug("destroying do_change window\n");
gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
SAFE_FREE(buffer);
state->name_type_new = type;
#endif
- gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer), state->name_buffer_new);
- if (state->name_type_new == 3) {
- gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Domain:");
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
+ state->name_buffer_new);
+ if (state->name_type_new == NetSetupDomainName) {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Domain:");
} else {
- gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Workgroup:");
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Workgroup:");
}
}
}
uint32_t unjoin_flags = 0;
gboolean domain_join = FALSE;
gboolean try_unjoin = FALSE;
- const char *domain_or_workgroup = NULL;
+ const char *new_workgroup_type = NULL;
+ const char *initial_workgroup_type = NULL;
struct join_state *state = (struct join_state *)data;
gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
}
+ switch (state->name_type_initial) {
+ case NetSetupWorkgroupName:
+ initial_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ initial_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
+ switch (state->name_type_new) {
+ case NetSetupWorkgroupName:
+ new_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ new_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
if (state->name_type_new == NetSetupDomainName) {
domain_join = TRUE;
join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
- domain_or_workgroup = "domain";
- } else {
- domain_or_workgroup = "workgroup";
}
if ((state->name_type_initial == NetSetupDomainName) &&
}
debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
- domain_or_workgroup,
+ new_workgroup_type,
state->name_buffer_new,
join_flags);
if (domain_join) {
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"The following error occured attempting to unjoin the %s: \"%s\": %s",
- domain_or_workgroup,
- state->name_buffer_new,
+ initial_workgroup_type,
+ state->name_buffer_initial,
err_str);
g_signal_connect_swapped(dialog, "response",
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"The following error occured attempting to join the %s: \"%s\": %s",
- domain_or_workgroup,
+ new_workgroup_type,
state->name_buffer_new,
err_str);
}
debug("callback_do_join: Successfully joined %s\n",
- domain_or_workgroup);
+ new_workgroup_type);
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_BUTTONS_OK,
"Welcome to the %s %s.",
state->name_buffer_new,
- domain_or_workgroup);
+ new_workgroup_type);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
debug("callback_do_change called\n");
+#if 0
+ /* FIXME: add proper warnings for Samba as a DC */
if (state->server_role == 3) {
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
gtk_widget_show(dialog);
return;
}
+#endif
state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
- gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500); /* breite * höhe */
+ gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
g_signal_connect(G_OBJECT(window), "delete_event",
char *str = NULL;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ asprintf(&str, "%s.%s", entry_text,
+ state->my_dnsdomain);
} else {
asprintf(&str, "%s.", entry_text);
}
- gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
+ str);
free(str);
gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
- gtk_box_pack_start(GTK_BOX(box1), state->label_full_computer_name, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(box1),
+ state->label_full_computer_name, TRUE, TRUE, 0);
gtk_widget_show(state->label_full_computer_name);
}
G_CALLBACK(callback_continue),
(gpointer)state);
if (state->name_type_initial == NetSetupDomainName) {
- gtk_entry_set_text(GTK_ENTRY(state->entry_domain), state->name_buffer_initial);
+ gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
+ state->name_buffer_initial);
gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
gtk_widget_set_sensitive(state->entry_domain, TRUE);
}
G_CALLBACK(callback_do_join_workgroup),
(gpointer)state);
{
- gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup), MAX_NETBIOS_NAME_LEN);
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
+ MAX_NETBIOS_NAME_LEN);
g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
G_CALLBACK(callback_enter_workgroup_and_unlock),
(gpointer)state);
(gpointer)state);
if (state->name_type_initial == NetSetupWorkgroupName) {
- gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup), state->name_buffer_initial);
+ gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
+ state->name_buffer_initial);
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
}
icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
&error);
if (icon == NULL) {
- g_print("failed to load logo from %s : %s\n",
+ g_print("failed to load icon from %s : %s\n",
SAMBA_ICON_PATH, error->message);
}
#if 1
- image = gtk_image_new_from_file(SAMBA_IMAGE_PATH);
+ image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
#else
image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
#endif
+ if (image == NULL) {
+ g_print("failed to load logo from %s : %s\n",
+ SAMBA_IMAGE_PATH_SMALL, error->message);
+ }
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
state->window_main = window;
gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
- gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600); /* breite * höhe */
+ gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
{
/* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
- gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+/* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
gtk_widget_show(image);
/* Label */
label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
- gtk_widget_set_size_request(GTK_WIDGET(label), 500, 40);
+/* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
/*
* Unix SMB/CIFS implementation.
* Join Support (cmdline + netapi)
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
if (argc < 2) {
printf("usage: netdomjoin\n");
- printf("\t[hostname=HOSTNAME] [domain=DOMAIN] <ou=OU> <usero=USERO> <passwordo=PASSWORDO> <userd=USERD> <passwordd=PASSWORDD>\n");
+ printf("\t[hostname] [domain=DOMAIN] <ou=OU> "
+ "<usero=USERO> <passwordo=PASSWORDO> "
+ "<userd=USERD> <passwordd=PASSWORDD> "
+ "<debug=DEBUGLEVEL>\n");
return 0;
}
str = get_string_param(argv[i]);
libnetapi_set_password(ctx, str);
}
+ if (strncasecmp(argv[i], "debug", strlen("debug"))== 0) {
+ const char *str = NULL;
+ str = get_string_param(argv[i]);
+ libnetapi_set_debuglevel(ctx, str);
+ }
}
status = NetJoinDomain(server_name,
/*
* Unix SMB/CIFS implementation.
* NetApi Join Support
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
if (!NT_STATUS_IS_OK(status)) {
return ntstatus_to_werror(status);
}
- r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx,
+ info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
}
if (account_ou) {
}
if (password) {
- r->in.password = talloc_strdup(mem_ctx, password);
- W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ r->in.admin_password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
}
r->in.join_flags = join_flags;
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
- struct wkssvc_PasswordBuffer encrypted_password;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
NTSTATUS status;
WERROR werr;
unsigned int old_timeout = 0;
- ZERO_STRUCT(encrypted_password);
-
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
server_name, domain_name,
account_ou, Account,
- &encrypted_password,
+ encrypted_password,
join_flags, &werr);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
W_ERROR_NOT_OK_RETURN(werr);
if (server_name) {
- r->in.server_name = talloc_strdup(mem_ctx, server_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx, server_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
} else {
NTSTATUS status;
if (!NT_STATUS_IS_OK(status)) {
return ntstatus_to_werror(status);
}
- r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx,
+ info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
}
if (account) {
}
if (password) {
- r->in.password = talloc_strdup(mem_ctx, password);
- W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ r->in.admin_password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
}
r->in.unjoin_flags = unjoin_flags;
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
- struct wkssvc_PasswordBuffer encrypted_password;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
NTSTATUS status;
WERROR werr;
unsigned int old_timeout = 0;
- ZERO_STRUCT(encrypted_password);
-
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
server_name,
account,
- &encrypted_password,
+ encrypted_password,
unjoin_flags,
&werr);
if (!NT_STATUS_IS_OK(status)) {
* -N,--no-pass
* -S,--signing
* -P --machine-pass
+ * -e --encrypt
*/
case 'N':
set_cmdline_auth_info_password("");
break;
+ case 'e':
+ set_cmdline_auth_info_smb_encrypt();
+ break;
+
}
}
{ "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" },
{ "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" },
{"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" },
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
POPT_TABLEEND
};
NULL, /* password */
false, /* got_pass */
false, /* use_kerberos */
- Undefined /* signing state */
+ Undefined, /* signing state */
+ false /* smb_encrypt */
};
const char *get_cmdline_auth_info_username(void)
cmdline_auth_info.got_pass = true;
}
+/* This should only be used by lib/popt_common.c JRA */
+void set_cmdline_auth_info_smb_encrypt(void)
+{
+ cmdline_auth_info.smb_encrypt = true;
+}
+
bool get_cmdline_auth_info_got_pass(void)
{
return cmdline_auth_info.got_pass;
}
+bool get_cmdline_auth_info_smb_encrypt(void)
+{
+ return cmdline_auth_info.smb_encrypt;
+}
+
bool get_cmdline_auth_info_copy(struct user_auth_info *info)
{
*info = cmdline_auth_info;
return len;
}
-/****************************************************************************
- Wrapper for receive_smb_raw().
- Checks the MAC on signed packets.
-****************************************************************************/
-
-bool receive_smb(int fd, char *buffer, unsigned int timeout, enum smb_read_errors *pre)
-{
- if (receive_smb_raw(fd, buffer, timeout, 0, pre) < 0) {
- return false;
- }
-
- if (srv_encryption_on()) {
- NTSTATUS status = srv_decrypt_buffer(buffer);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("receive_smb: SMB decryption failed "
- "on incoming packet! Error %s\n",
- nt_errstr(status) ));
- cond_set_smb_read_error(pre, SMB_READ_BAD_DECRYPT);
- return false;
- }
- }
-
- /* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(buffer, true)) {
- DEBUG(0, ("receive_smb: SMB Signature verification "
- "failed on incoming packet!\n"));
- cond_set_smb_read_error(pre,SMB_READ_BAD_SIG);
- return false;
- }
-
- return true;
-}
-
-/****************************************************************************
- Send an smb to a fd.
-****************************************************************************/
-
-bool send_smb(int fd, char *buffer)
-{
- size_t len;
- size_t nwritten=0;
- ssize_t ret;
- char *buf_out = buffer;
-
- /* Sign the outgoing packet if required. */
- srv_calculate_sign_mac(buf_out);
-
- if (srv_encryption_on()) {
- NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("send_smb: SMB encryption failed "
- "on outgoing packet! Error %s\n",
- nt_errstr(status) ));
- return false;
- }
- }
-
- len = smb_len(buf_out) + 4;
-
- while (nwritten < len) {
- ret = write_data(fd,buf_out+nwritten,len - nwritten);
- if (ret <= 0) {
- DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
- (int)len,(int)ret, strerror(errno) ));
- srv_free_enc_buffer(buf_out);
- return false;
- }
- nwritten += ret;
- }
-
- srv_free_enc_buffer(buf_out);
- return true;
-}
-
/****************************************************************************
Open a socket of the specified type, port, and address for incoming data.
****************************************************************************/
{
LDAP *ldp = NULL;
+
+ DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout "
+ "%u seconds\n", server, port, to));
+
/* Setup timeout */
gotalarm = 0;
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
ldp = ldap_open(server, port);
if (ldp == NULL) {
- DEBUG(2,("Could not open LDAP connection to %s:%d: %s\n",
+ DEBUG(2,("Could not open connection to LDAP server %s:%d: %s\n",
server, port, strerror(errno)));
+ } else {
+ DEBUG(10, ("Connected to LDAP server '%s:%d'\n", server, port));
}
/* Teardown timeout. */
got_connection:
print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
- DEBUG(3,("Connected to LDAP server %s\n", addr));
+ DEBUG(3,("Successfully contacted LDAP server %s\n", addr));
if (!ads->auth.user_name) {
/* Must use the userPrincipalName value here or sAMAccountName
/* Otherwise setup the TCP LDAP session */
- if ( (ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
- LDAP_PORT, lp_ldap_timeout())) == NULL )
- {
+ ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
+ LDAP_PORT, lp_ldap_timeout());
+ if (ads->ldap.ld == NULL) {
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
}
+ DEBUG(3,("Connected to LDAP server %s\n", ads->config.ldap_server_name));
/* cache the successful connection for workgroup and realm */
if (ads_closest_dc(ads)) {
* Unix SMB/CIFS implementation.
* libnet Join Support
* Copyright (C) Gerald (Jerry) Carter 2006
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "libnet/libnet_join.h"
#include "libnet/libnet_proto.h"
-static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
- struct libnet_JoinCtx *r)
+static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
+{
+ if (!secrets_store_domain_sid(r->out.netbios_domain_name,
+ r->out.domain_sid))
+ {
+ return false;
+ }
+
+ if (!secrets_store_machine_password(r->in.machine_password,
+ r->out.netbios_domain_name,
+ SEC_CHAN_WKSTA))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
- const char *password = NULL;
POLICY_HND sam_pol, domain_pol, user_pol, lsa_pol;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *acct_name;
DATA_BLOB digested_session_key;
uchar md4_trust_password[16];
- password = talloc_strdup(mem_ctx,
- generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH));
- NT_STATUS_HAVE_NO_MEMORY(password);
+ if (!r->in.machine_password) {
+ r->in.machine_password = talloc_strdup(mem_ctx, generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH));
+ NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
+ }
- status = cli_full_connection(&cli, NULL, r->in.server_name,
+ status = cli_full_connection(&cli, NULL,
+ r->in.dc_name,
NULL, 0,
"IPC$", "IPC",
r->in.admin_account,
- NULL, //r->in.domain_name,
- r->in.password,
- 0, Undefined, NULL);
+ NULL,
+ r->in.admin_password,
+ 0,
+ Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
goto done;
goto done;
}
- E_md4hash(password, md4_trust_password);
- encode_pw_buffer(pwbuf, password, STR_UNICODE);
+ E_md4hash(r->in.machine_password, md4_trust_password);
+ encode_pw_buffer(pwbuf, r->in.machine_password, STR_UNICODE);
generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
MD5Init(&md5ctx);
MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
- MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
+ MD5Update(&md5ctx, cli->user_session_key.data,
+ cli->user_session_key.length);
MD5Final(digested_session_key.data, &md5ctx);
SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
cli_rpc_pipe_close(pipe_hnd);
- if (!secrets_store_domain_sid(r->out.netbios_domain_name,
- r->out.domain_sid))
- {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
- if (!secrets_store_machine_password(password,
- r->out.netbios_domain_name,
- SEC_CHAN_WKSTA))
- {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
status = NT_STATUS_OK;
done:
if (cli) {
return status;
}
-static NTSTATUS do_DomainUnjoin(TALLOC_CTX *mem_ctx,
- struct libnet_UnjoinCtx *r)
+static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX *mem_ctx,
+ struct libnet_UnjoinCtx *r)
+{
+ if (!secrets_delete_machine_password_ex(lp_workgroup())) {
+ return false;
+ }
+
+ if (!secrets_delete_domain_sid(lp_workgroup())) {
+ return false;
+ }
+
+ return true;
+}
+
+static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
+ struct libnet_UnjoinCtx *r)
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
SAM_USERINFO_CTR ctr, *qctr = NULL;
SAM_USER_INFO_16 p16;
- status = cli_full_connection(&cli, NULL, r->in.server_name,
+ status = cli_full_connection(&cli, NULL,
+ r->in.dc_name,
NULL, 0,
"IPC$", "IPC",
r->in.admin_account,
- NULL, //r->in.domain_name,
- r->in.password,
+ NULL,
+ r->in.admin_password,
0, Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
- if (!secrets_delete_machine_password_ex(lp_workgroup())) {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
- if (!secrets_delete_domain_sid(lp_workgroup())) {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
done:
- rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
- rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
-
- cli_rpc_pipe_close(pipe_hnd);
+ if (pipe_hnd) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+ rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
+ cli_rpc_pipe_close(pipe_hnd);
+ }
if (cli) {
cli_shutdown(cli);
if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- status = do_DomainJoin(mem_ctx, r);
+ status = libnet_join_joindomain_rpc(mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
return WERR_SETUP_ALREADY_JOINED;
}
return ntstatus_to_werror(status);
}
+
+ if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) {
+ return WERR_SETUP_NOT_JOINED;
+ }
}
werr = do_JoinConfig(r);
if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- status = do_DomainUnjoin(mem_ctx, r);
+ status = libnet_join_unjoindomain_rpc(mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
return WERR_SETUP_NOT_JOINED;
}
return ntstatus_to_werror(status);
}
+
+ libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
}
werr = do_UnjoinConfig(r);
/*
* Unix SMB/CIFS implementation.
* libnet Join Support
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
struct libnet_JoinCtx {
struct {
- const char *server_name;
+ const char *dc_name;
+ const char *machine_name;
const char *domain_name;
const char *account_ou;
const char *admin_account;
- const char *password;
+ const char *admin_password;
+ const char *machine_password;
uint32_t join_flags;
const char *os_version;
const char *os_string;
struct libnet_UnjoinCtx {
struct {
- const char *server_name;
+ const char *dc_name;
const char *domain_name;
const char *admin_account;
- const char *password;
+ const char *admin_password;
uint32_t unjoin_flags;
bool modify_config;
struct dom_sid *domain_sid;
Ensure a connection is encrypted.
********************************************************************/
-static bool force_cli_encryption(struct cli_state *c,
+NTSTATUS cli_cm_force_encryption(struct cli_state *c,
const char *username,
const char *password,
const char *domain,
const char *sharename)
{
- uint16 major, minor;
- uint32 caplow, caphigh;
- NTSTATUS status;
+ NTSTATUS status = cli_force_encryption(c,
+ username,
+ password,
+ domain);
- if (!SERVER_HAS_UNIX_CIFS(c)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED)) {
d_printf("Encryption required and "
"server that doesn't support "
"UNIX extensions - failing connect\n");
- return false;
- }
-
- if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNKNOWN_REVISION)) {
d_printf("Encryption required and "
"can't get UNIX CIFS extensions "
"version from server.\n");
- return false;
- }
-
- if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
d_printf("Encryption required and "
"share %s doesn't support "
"encryption.\n", sharename);
- return false;
- }
-
- if (c->use_kerberos) {
- status = cli_gss_smb_encryption_start(c);
- } else {
- status = cli_raw_ntlm_smb_encryption_start(c,
- username,
- password,
- domain);
- }
-
- if (!NT_STATUS_IS_OK(status)) {
+ } else if (!NT_STATUS_IS_OK(status)) {
d_printf("Encryption required and "
"setup failed with error %s.\n",
nt_errstr(status));
- return false;
}
- return true;
+ return status;
}
/********************************************************************
return NULL;
}
- if (force_encrypt && !force_cli_encryption(c,
+ if (force_encrypt) {
+ status = cli_cm_force_encryption(c,
username,
password,
lp_workgroup(),
- sharename)) {
- cli_shutdown(c);
- return NULL;
+ sharename);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_shutdown(c);
+ return NULL;
+ }
}
DEBUG(4,(" tconx ok\n"));
return false;
}
- if (force_encrypt && !force_cli_encryption(cli,
+ if (force_encrypt) {
+ NTSTATUS status = cli_cm_force_encryption(cli,
username,
password,
lp_workgroup(),
- "IPC$")) {
- return false;
+ "IPC$");
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
}
res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
return NT_STATUS_NOT_SUPPORTED;
}
#endif
+
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+NTSTATUS cli_force_encryption(struct cli_state *c,
+ const char *username,
+ const char *password,
+ const char *domain)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+
+ if (!SERVER_HAS_UNIX_CIFS(c)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ return NT_STATUS_UNKNOWN_REVISION;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ return NT_STATUS_UNSUPPORTED_COMPRESSION;
+ }
+
+ if (c->use_kerberos) {
+ return cli_gss_smb_encryption_start(c);
+ }
+ return cli_raw_ntlm_smb_encryption_start(c,
+ username,
+ password,
+ domain);
+}
{ "WERR_REG_CORRUPT", WERR_REG_CORRUPT },
{ "WERR_REG_IO_FAILURE", WERR_REG_IO_FAILURE },
{ "WERR_REG_FILE_INVALID", WERR_REG_FILE_INVALID },
+ { "WERR_NO_SUCH_SERVICE", WERR_NO_SUCH_SERVICE },
{ "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED },
{ "WERR_CAN_NOT_COMPLETE", WERR_CAN_NOT_COMPLETE},
{ "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS},
Copyright (C) John Terpstra 2000
Copyright (C) Tom Jansen (Ninja ISD) 2002
Copyright (C) Derrell Lipman 2003, 2004
+ Copyright (C) Jeremy Allison 2007, 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
password, strlen(password)+1);
}
+ /*
+ * We don't need to renegotiate encryption
+ * here as the encryption context is not per
+ * tid.
+ */
+
if (! cli_send_tconX(srv->cli, share, "?????",
password, strlen(password)+1)) {
DEBUG(4,(" tconx ok\n"));
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(c,
+ username_used,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(c);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok\n"));
+ }
+
/*
* Ok, we have got a nice connection
* Let's allocate a server structure.
return NULL;
}
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
+ username,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed on IPC$\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(ipc_cli);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok on IPC$\n"));
+ }
+
ipc_srv = SMB_MALLOC_P(SMBCSRV);
if (!ipc_srv) {
errno = ENOMEM;
bool b;
smbc_get_auth_data_with_context_fn auth_fn;
void *v;
+ const char *s;
} option_value;
va_start(ap, option_name);
*/
option_value.v = va_arg(ap, void *);
context->internal->_user_data = option_value.v;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Save an encoded value for encryption level.
+ * 0 = off, 1 = attempt, 2 = required.
+ */
+ option_value.s = va_arg(ap, const char *);
+ if (strcmp(option_value.s, "none") == 0) {
+ context->internal->_smb_encryption_level = 0;
+ } else if (strcmp(option_value.s, "request") == 0) {
+ context->internal->_smb_encryption_level = 1;
+ } else if (strcmp(option_value.s, "require") == 0) {
+ context->internal->_smb_encryption_level = 2;
+ }
}
va_end(ap);
* with smbc_option_get()
*/
return context->internal->_user_data;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Return the current smb encrypt negotiate option as a string.
+ */
+ switch (context->internal->_smb_encryption_level) {
+ case 0:
+ return (void *) "none";
+ case 1:
+ return (void *) "request";
+ case 2:
+ return (void *) "require";
+ }
+ } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
+ /*
+ * Return the current smb encrypt status option as a bool.
+ * false = off, true = on. We don't know what server is
+ * being requested, so we only return true if all servers
+ * are using an encrypted connection.
+ */
+ SMBCSRV *s;
+ unsigned int num_servers = 0;
+
+ for (s = context->internal->_servers; s; s = s->next) {
+ num_servers++;
+ if (s->cli->trans_enc_state == NULL) {
+ return (void *)false;
+ }
+ }
+ return (void *) (bool) (num_servers > 0);
}
return NULL;
Pull out the encryption context for this packet. 0 means global context.
******************************************************************************/
-NTSTATUS get_enc_ctx_num(const char *buf, uint16 *p_enc_ctx_num)
+NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
{
if (smb_len(buf) < 8) {
return NT_STATUS_INVALID_BUFFER_SIZE;
}
- if (buf[4] == (char)0xFF) {
+ if (buf[4] == 0xFF) {
if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
/* Not an encrypted buffer. */
return NT_STATUS_NOT_FOUND;
memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
- /* Reset the length. */
- _smb_setlen(buf,data_len + 4);
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf,data_len + 4);
SAFE_FREE(inbuf);
return NT_STATUS_OK;
}
memcpy(buf + 8, out_buf.value, out_buf.length);
- _smb_setlen(buf, out_buf.length + 4);
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf, out_buf.length + 4);
gss_release_buffer(&minor, &out_buf);
return NT_STATUS_OK;
{
/* We know this is an smb buffer, and we
* didn't malloc, only copy, for a keepalive,
- * so ignore session keepalives. */
+ * so ignore non-session messages. */
- if(CVAL(buf,0) == SMBkeepalive) {
+ if(CVAL(buf,0)) {
return;
}
NTSTATUS status;
uint16 enc_ctx_num;
- /* Ignore session keepalives. */
- if(CVAL(cli->inbuf,0) == SMBkeepalive) {
+ /* Ignore non-session messages. */
+ if(CVAL(cli->inbuf,0)) {
return NT_STATUS_OK;
}
- status = get_enc_ctx_num(cli->inbuf, &enc_ctx_num);
+ status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
{
- /* Ignore session keepalives. */
- if(CVAL(cli->outbuf,0) == SMBkeepalive) {
+ /* Ignore non-session messages. */
+ if(CVAL(cli->outbuf,0)) {
return NT_STATUS_OK;
}
bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
{
- /* Check if it's a session keepalive. */
- if(CVAL(inbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(inbuf,0)) {
return True;
}
void srv_calculate_sign_mac(char *outbuf)
{
- /* Check if it's a session keepalive. */
- if(CVAL(outbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(outbuf,0)) {
return;
}
void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
const char *pwd,
DATA_BLOB *session_key,
- struct wkssvc_PasswordBuffer *pwd_buf)
+ struct wkssvc_PasswordBuffer **pwd_buf)
{
uint8_t buffer[516];
struct MD5Context ctx;
-
- DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
-
+ struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
+ DATA_BLOB confounded_session_key;
int confounder_len = 8;
uint8_t confounder[8];
+ my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
+ if (!my_pwd_buf) {
+ return;
+ }
+
+ confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
+
encode_pw_buffer(buffer, pwd, STR_UNICODE);
generate_random_buffer((uint8_t *)confounder, confounder_len);
SamOEMhashBlob(buffer, 516, &confounded_session_key);
- memcpy(&pwd_buf->data[0], confounder, confounder_len);
- memcpy(&pwd_buf->data[8], buffer, 516);
+ memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
+ memcpy(&my_pwd_buf->data[8], buffer, 516);
data_blob_free(&confounded_session_key);
+
+ *pwd_buf = my_pwd_buf;
}
WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
for (i = 0; i < lck->num_share_modes; i++) {
struct share_mode_entry *entry_p = &lck->share_modes[i];
- char *str = share_mode_str(NULL, i, entry_p);
+ char *str = NULL;
+ if (DEBUGLEVEL >= 10) {
+ str = share_mode_str(NULL, i, entry_p);
+ }
DEBUG(10,("parse_share_modes: %s\n",
str ? str : ""));
if (!process_exists(entry_p->pid)) {
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next) {
- run_any_election |= work->RunningElection;
+ if (work->RunningElection) {
+ run_any_election = work->RunningElection;
+ }
/*
* Start an election if we have any chance of winning.
}
/*******************************************************************
- Ensure we don't use sendfile if server smb signing or selaing is active.
+ Ensure we don't use sendfile if server smb signing is active.
********************************************************************/
bool lp_use_sendfile(int snum)
}
return (_lp_use_sendfile(snum) &&
(get_remote_arch() != RA_WIN95) &&
- !srv_is_signing_active() &&
- !srv_encryption_on());
+ !srv_is_signing_active());
}
/*******************************************************************
goto err_exit;
}
- create_directory(conn, new_dir);
+ create_directory(conn, NULL, new_dir);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
uint32 vers_id;
if ( tdb_reg )
- return True;
+ return true;
if ( !(tdb_reg = tdb_wrap_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600)) )
{
if ( !tdb_reg ) {
DEBUG(0,("regdb_init: Failed to open registry %s (%s)\n",
state_path("registry.tdb"), strerror(errno) ));
- return False;
+ return false;
}
DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
/* always setup the necessary keys and values */
if ( !init_registry_data() ) {
- DEBUG(0,("init_registry: Failed to initialize data in registry!\n"));
- return False;
+ DEBUG(0,("regdb_init: Failed to initialize data in registry!\n"));
+ return false;
}
- return True;
+ return true;
}
/***********************************************************************
int regdb_close( void )
{
+ if (tdb_refcount == 0) {
+ return 0;
+ }
+
tdb_refcount--;
DEBUG(10,("regdb_close: decrementing refcount (%d)\n", tdb_refcount));
uint8 *buffer = NULL;
int i = 0;
uint32 len, buflen;
- bool ret = True;
+ bool ret = true;
uint32 num_subkeys = regsubkey_ctr_numkeys(ctr);
char *keyname = NULL;
TALLOC_CTX *ctx = talloc_tos();
/* allocate some initial memory */
if (!(buffer = (uint8 *)SMB_MALLOC(1024))) {
- return False;
+ return false;
}
buflen = 1024;
len = 0;
/* allocate some extra space */
if ((buffer = (uint8 *)SMB_REALLOC( buffer, len*2 )) == NULL) {
DEBUG(0,("regdb_store_keys: Failed to realloc memory of size [%d]\n", len*2));
- ret = False;
+ ret = false;
goto done;
}
buflen = len*2;
dbuf.dptr = buffer;
dbuf.dsize = len;
if ( tdb_store_bystring( tdb_reg->tdb, keyname, dbuf, TDB_REPLACE ) == -1) {
- ret = False;
+ ret = false;
goto done;
}
&& (memcmp(old_data.dptr, data.dptr, data.dsize) == 0)) {
SAFE_FREE(old_data.dptr);
SAFE_FREE(data.dptr);
- return True;
+ return true;
}
ret = tdb_trans_store_bystring(tdb_reg->tdb, keystr, data, TDB_REPLACE);
goto done;
}
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(cli,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ "IPC$");
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ result = 1;
+ goto done;
+ }
+ }
+
#if 0 /* COMMENT OUT FOR TESTING */
memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
#endif
# this runs the file serving tests that are expected to pass with samba3
-if [ $# != 2 ]; then
+if [ $# -lt 2 ]; then
cat <<EOF
Usage: test_smbclient_s3.sh SERVER SERVER_IP
EOF
SERVER="$1"
SERVER_IP="$2"
SMBCLIENT="$VALGRIND ${SMBCLIENT:-$BINDIR/smbclient} $CONFIGURATION"
+shift 2
+ADDARGS="$*"
incdir=`dirname $0`
. $incdir/test_functions.sh
prompt="smb"
echo du | \
- $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I SERVER_IP 2>&1 | \
+ $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I SERVER_IP $ADDARGS 2>&1 | \
grep $prompt
if [ $? = 0 ] ; then
CLI_FORCE_INTERACTIVE=yes \
$SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP \
- < $tmpfile 2>/dev/null | \
+ $ADDARGS < $tmpfile 2>/dev/null | \
grep $prompt
if [ $? = 0 ] ; then
fi
start=""
name="$t"
- testit "$name" $VALGRIND $BINDIR/smbtorture $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
+ testit "$name" $VALGRIND $BINDIR/smbtorture $unc -U"$username"%"$password" $ADDARGS $t || failed=`expr $failed + 1`
done
testok $0 $failed
$SCRIPTDIR/test_local_s3.sh || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" || failed=`expr $failed + $?`
+echo "Testing encrypted"
+$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" "-e" || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP || failed=`expr $failed + $?`
+echo "Testing encrypted"
+$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP "-e" || failed=`expr $failed + $?`
$SCRIPTDIR/test_wbinfo_s3.sh $WORKGROUP $SERVER $USERNAME $PASSWORD || failed=`expr $failed + $?`
LD_LIBRARY_PATH="$SAMBA4SHAREDDIR:$LD_LIBRARY_PATH"
}
construct_reply_common((char *)req->inbuf, aio_ex->outbuf);
- srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True);
+ srv_set_message(aio_ex->outbuf, 12, 0, True);
SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
a = &aio_ex->acb;
SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
show_msg(aio_ex->outbuf);
- if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) {
- exit_server_cleanly("handle_aio_write: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("handle_aio_write: srv_send_smb "
"failed.");
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
int ret = 0;
int outsize;
char *outbuf = aio_ex->outbuf;
- const char *inbuf = aio_ex->inbuf;
char *data = smb_buf(outbuf);
ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
ret = errno;
ERROR_NT(map_nt_error_from_unix(ret));
- outsize = srv_set_message(inbuf,outbuf,0,0,true);
+ outsize = srv_set_message(outbuf,0,0,true);
} else {
- outsize = srv_set_message(inbuf, outbuf,12,nread,False);
+ outsize = srv_set_message(outbuf,12,nread,False);
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
(int)aio_ex->acb.aio_nbytes, (int)nread ) );
}
- _smb_setlen(outbuf,outsize - 4);
+ smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("handle_aio_read_complete: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),outbuf,
+ IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) {
+ exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
"failed.");
}
ret = errno;
ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull);
- srv_set_message(inbuf,outbuf,0,0,true);
+ srv_set_message(outbuf,0,0,true);
} else {
bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0);
NTSTATUS status;
ret = errno;
ERROR_BOTH(map_nt_error_from_unix(ret),
ERRHRD, ERRdiskfull);
- srv_set_message(inbuf,outbuf,0,0,true);
+ srv_set_message(outbuf,0,0,true);
DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
fsp->fsp_name, nt_errstr(status) ));
}
}
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("handle_aio_write: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
}
DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
enum brl_type lock_type;
char *inbuf;
int length;
+ bool encrypted;
} blocking_lock_record;
/* dlink list we store pending lock records on. */
****************************************************************************/
bool push_blocking_lock_request( struct byte_range_lock *br_lck,
- const char *inbuf, int length,
+ const struct smb_request *req,
files_struct *fsp,
int lock_timeout,
int lock_num,
uint32 blocking_pid)
{
static bool set_lock_msg;
+ size_t length = smb_len(req->inbuf)+4;
blocking_lock_record *blr;
NTSTATUS status;
return False;
}
- blr->com_type = CVAL(inbuf,smb_com);
+ blr->com_type = CVAL(req->inbuf,smb_com);
blr->fsp = fsp;
if (lock_timeout == -1) {
blr->expire_time.tv_sec = 0;
blr->lock_type = lock_type;
blr->offset = offset;
blr->count = count;
- memcpy(blr->inbuf, inbuf, length);
+ memcpy(blr->inbuf, req->inbuf, length);
blr->length = length;
+ blr->encrypted = req->encrypted;
/* Add a pending lock record for this. */
status = brl_lock(smbd_messaging_context(), br_lck,
set_lock_msg = True;
}
- DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with "
+ DEBUG(3,("push_blocking_lock_request: lock request length=%u blocked with "
"expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
- length, (unsigned int)blr->expire_time.tv_sec,
+ (unsigned int)length, (unsigned int)blr->expire_time.tv_sec,
(unsigned int)blr->expire_time.tv_usec, lock_timeout,
blr->fsp->fnum, blr->fsp->fsp_name ));
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
return True;
}
smb_panic("Could not allocate smb_request");
}
- init_smb_request(req, (uint8 *)blr->inbuf, 0);
+ init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
reply_outbuf(req, 2, 0);
/*
chain_reply(req);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
- exit_server_cleanly("send_blocking_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+ exit_server_cleanly("send_blocking_reply: srv_send_smb failed.");
}
}
/* Store the last lock error. */
files_struct *fsp = blr->fsp;
- fsp->last_lock_failure.context.smbpid = blr->lock_pid;
- fsp->last_lock_failure.context.tid = fsp->conn->cnum;
- fsp->last_lock_failure.context.pid = procid_self();
- fsp->last_lock_failure.start = blr->offset;
- fsp->last_lock_failure.size = blr->count;
- fsp->last_lock_failure.fnum = fsp->fnum;
- fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
- fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ if (fsp) {
+ fsp->last_lock_failure.context.smbpid = blr->lock_pid;
+ fsp->last_lock_failure.context.tid = fsp->conn->cnum;
+ fsp->last_lock_failure.context.pid = procid_self();
+ fsp->last_lock_failure.start = blr->offset;
+ fsp->last_lock_failure.size = blr->count;
+ fsp->last_lock_failure.fnum = fsp->fnum;
+ fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
+ fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ }
}
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("generic_blocking_lock_error: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),outbuf, blr->encrypted)) {
+ exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
}
}
*/
SCVAL(outbuf,smb_com,SMBtrans2);
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("blocking_lock_reply_error: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ outbuf,
+ IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+ exit_server_cleanly("blocking_lock_reply_error: srv_send_smb failed.");
}
break;
}
return True;
}
- init_smb_request(req, (uint8 *)blr->inbuf, 0);
+ init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
SCVAL(req->inbuf, smb_com, SMBtrans2);
SSVAL(params,0,0);
/* Fake up max_data_bytes here - we know it fits. */
- send_trans2_replies(req, params, 2, NULL, 0, 0xffff);
+ send_trans2_replies(blr->fsp->conn, req, params, 2, NULL, 0, 0xffff);
return True;
}
locktype,
NT_STATUS_RANGE_NOT_LOCKED);
}
+ /* We're closing the file fsp here, so ensure
+ * we don't have a dangling pointer. */
+ blr->fsp = NULL;
}
}
}
}
}
-int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
{
- int outsize = srv_set_message(inbuf, outbuf,0,0,True);
+ int outsize = srv_set_message(outbuf,0,0,True);
error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
return outsize;
}
#define NERR_notsupported 50
-static void api_no_reply(struct smb_request *req);
+static void api_no_reply(connection_struct *conn, struct smb_request *req);
/*******************************************************************
copies parameters and data, as needed, into the smb buffer
Send a trans reply.
****************************************************************************/
-void send_trans_reply(struct smb_request *req,
+void send_trans_reply(connection_struct *conn,
+ struct smb_request *req,
char *rparam, int rparam_len,
char *rdata, int rdata_len,
bool buffer_too_large)
}
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("send_trans_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
TALLOC_FREE(req->outbuf);
}
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(), (char *)req->outbuf))
- exit_server_cleanly("send_trans_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
tot_data_sent += this_ldata;
tot_param_sent += this_lparam;
Start the first part of an RPC reply which began with an SMBtrans request.
****************************************************************************/
-static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
+static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req, smb_np_struct *p)
{
bool is_data_outstanding;
char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
&is_data_outstanding)) < 0) {
SAFE_FREE(rdata);
- api_no_reply(req);
+ api_no_reply(conn,req);
return;
}
- send_trans_reply(req, NULL, 0, rdata, data_len, is_data_outstanding);
+ send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding);
SAFE_FREE(rdata);
return;
}
WaitNamedPipeHandleState
****************************************************************************/
-static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
char *param, int param_len)
{
uint16 priority;
if (wait_rpc_pipe_hnd_state(p, priority)) {
/* now send the reply */
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
- api_no_reply(req);
+ api_no_reply(conn,req);
}
SetNamedPipeHandleState
****************************************************************************/
-static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
char *param, int param_len)
{
uint16 id;
if (set_rpc_pipe_hnd_state(p, id)) {
/* now send the reply */
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
- api_no_reply(req);
+ api_no_reply(conn,req);
}
When no reply is generated, indicate unsupported.
****************************************************************************/
-static void api_no_reply(struct smb_request *req)
+static void api_no_reply(connection_struct *conn, struct smb_request *req)
{
char rparam[4];
DEBUG(3,("Unsupported API fd command\n"));
/* now send the reply */
- send_trans_reply(req, rparam, 4, NULL, 0, False);
+ send_trans_reply(conn, req, rparam, 4, NULL, 0, False);
return;
}
/* Win9x does this call with a unicode pipe name, not a pnum. */
/* Just return success for now... */
DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
/* dce/rpc command */
reply = write_to_pipe(p, data, tdscnt);
if (!reply) {
- api_no_reply(req);
+ api_no_reply(conn, req);
return;
}
- api_rpc_trans_reply(req, p);
+ api_rpc_trans_reply(conn, req, p);
break;
case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
/* Wait Named Pipe Handle state */
- api_WNPHS(req, p, params, tpscnt);
+ api_WNPHS(conn, req, p, params, tpscnt);
break;
case TRANSACT_SETNAMEDPIPEHANDLESTATE:
/* Set Named Pipe Handle state */
- api_SNPHS(req, p, params, tpscnt);
+ api_SNPHS(conn, req, p, params, tpscnt);
break;
default:
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
state->max_data_return,
state->max_param_return);
- if (state->close_on_completion)
+ if (state->close_on_completion) {
close_cnum(conn,state->vuid);
+ req->conn = NULL;
+ }
return;
}
Reply to a SMBtrans.
****************************************************************************/
-void reply_trans(connection_struct *conn, struct smb_request *req)
+void reply_trans(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int dsoff;
unsigned int dscnt;
unsigned int psoff;
Reply to a secondary SMBtrans.
****************************************************************************/
-void reply_transs(connection_struct *conn, struct smb_request *req)
+void reply_transs(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
int size;
/* If api_Unsupported returns false we can't return anything. */
if (reply) {
- send_trans_reply(req, rparam, rparam_len,
+ send_trans_reply(conn, req, rparam, rparam_len,
rdata, rdata_len, False);
}
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sends(connection_struct *conn, struct smb_request *req)
+void reply_sends(struct smb_request *req)
{
struct msg_state *state;
int len;
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendstrt(connection_struct *conn, struct smb_request *req)
+void reply_sendstrt(struct smb_request *req)
{
char *p;
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendtxt(connection_struct *conn, struct smb_request *req)
+void reply_sendtxt(struct smb_request *req)
{
int len;
char *msg;
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendend(connection_struct *conn, struct smb_request *req)
+void reply_sendend(struct smb_request *req)
{
START_PROFILE(SMBsendend);
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_negprot(connection_struct *conn, struct smb_request *req)
+void reply_negprot(struct smb_request *req)
{
size_t size = smb_len(req->inbuf) + 4;
int choice= -1;
Setup the common parts of the return packet and send it.
*****************************************************************************/
-static void change_notify_reply_packet(const uint8 *request_buf,
+static void change_notify_reply_packet(connection_struct *conn,
+ const uint8 *request_buf,
NTSTATUS error_code)
{
- const char *inbuf = (const char *)request_buf;
char outbuf[smb_size+38];
memset(outbuf, '\0', sizeof(outbuf));
* Seems NT needs a transact command with an error code
* in it. This is a longer packet than a simple error.
*/
- srv_set_message((const char *)request_buf, outbuf,18,0,False);
+ srv_set_message(outbuf,18,0,False);
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server_cleanly("change_notify_reply_packet: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),
+ outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
"failed.");
}
-void change_notify_reply(const uint8 *request_buf, uint32 max_param,
+void change_notify_reply(connection_struct *conn,
+ const uint8 *request_buf, uint32 max_param,
struct notify_change_buf *notify_buf)
{
prs_struct ps;
uint8 tmp_request[smb_size];
if (notify_buf->num_changes == -1) {
- change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
notify_buf->num_changes = 0;
return;
}
* We exceed what the client is willing to accept. Send
* nothing.
*/
- change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
goto done;
}
if (!(req = talloc(talloc_tos(), struct smb_request))) {
- change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY);
goto done;
}
smb_setlen((char *)tmp_request, smb_size);
SCVAL(tmp_request, smb_wct, 0);
- init_smb_request(req, tmp_request,0);
+ init_smb_request(req, tmp_request,0, conn->encrypted_tid);
- send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps),
+ send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
prs_offset(&ps), NULL, 0);
done:
return status;
}
-NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
- uint32 filter, bool recursive,
- struct files_struct *fsp)
+NTSTATUS change_notify_add_request(const struct smb_request *req,
+ uint32 max_param,
+ uint32 filter, bool recursive,
+ struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
request->mid_map = map;
map->req = request;
- memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
+ memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf));
request->max_param = max_param;
request->filter = filter;
request->fsp = fsp;
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
- map->mid = SVAL(inbuf, smb_mid);
+ map->mid = SVAL(req->inbuf, smb_mid);
DLIST_ADD(notify_changes_by_mid, map);
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
return NT_STATUS_OK;
}
return;
}
- change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED);
+ change_notify_reply_packet(map->req->fsp->conn,
+ map->req->request_buf, NT_STATUS_CANCELLED);
change_notify_remove_request(map->req);
}
}
while (fsp->notify->requests != NULL) {
- change_notify_reply_packet(
+ change_notify_reply_packet(fsp->conn,
fsp->notify->requests->request_buf, status);
change_notify_remove_request(fsp->notify->requests);
}
* TODO: do we have to walk the lists of requests pending?
*/
- change_notify_reply(fsp->notify->requests->request_buf,
+ change_notify_reply(fsp->conn,
+ fsp->notify->requests->request_buf,
fsp->notify->requests->max_param,
fsp->notify);
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-void send_nt_replies(struct smb_request *req, NTSTATUS nt_error,
+void send_nt_replies(connection_struct *conn,
+ struct smb_request *req, NTSTATUS nt_error,
char *params, int paramsize,
char *pdata, int datasize)
{
/* Send the packet */
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
- exit_server_cleanly("send_nt_replies: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn))) {
+ exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
}
TALLOC_FREE(req->outbuf);
Reply to an NT create and X call.
****************************************************************************/
-void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req)
+void reply_ntcreate_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 flags;
uint32 access_mask;
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
return;
}
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
return;
}
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ntcancel(connection_struct *conn, struct smb_request *req)
+void reply_ntcancel(struct smb_request *req)
{
/*
* Go through and cancel any pending change notifies.
Reply to a NT rename request.
****************************************************************************/
-void reply_ntrename(connection_struct *conn, struct smb_request *req)
+void reply_ntrename(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *oldname = NULL;
char *newname = NULL;
char *p;
* here.
*/
- change_notify_reply(req->inbuf, max_param_count, fsp->notify);
+ change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify);
/*
* change_notify_reply() above has independently sent its
* No changes pending, queue the request
*/
- status = change_notify_add_request(req->inbuf, max_param_count, filter,
+ status = change_notify_add_request(req,
+ max_param_count,
+ filter,
recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
/*
* Rename was successful.
*/
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
fsp->fsp_name, new_name));
SIVAL(params,0,(uint32)sd_size);
if (max_data_count < sd_size) {
- send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL,
+ send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
params, 4, *ppdata, 0);
TALLOC_FREE(frame);
return;
SMB_ASSERT(sd_size == blob.length);
memcpy(data, blob.data, sd_size);
- send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
TALLOC_FREE(frame);
return;
}
done:
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
}
so we can know if we need to pre-allocate or not */
DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
case FSCTL_CREATE_OR_GET_OBJECT_ID:
push_file_id_16(pdata, &fsp->file_id);
memcpy(pdata+16,create_volume_objectid(conn,objid),16);
push_file_id_16(pdata+32, &fsp->file_id);
- send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
pdata, data_count);
return;
}
talloc_destroy(shadow_data->mem_ctx);
- send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
pdata, data_count);
return;
*/
/* this works for now... */
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
}
default:
break;
}
- send_nt_replies(req, nt_status, params, param_len,
+ send_nt_replies(conn, req, nt_status, params, param_len,
pdata, data_len);
}
return;
}
- send_nt_replies(req, NT_STATUS_OK, params, param_len,
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
pdata, data_len);
}
#endif /* HAVE_SYS_QUOTAS */
Reply to a SMBNTtrans.
****************************************************************************/
-void reply_nttrans(connection_struct *conn, struct smb_request *req)
+void reply_nttrans(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint32 pscnt;
uint32 psoff;
uint32 dscnt;
Reply to a SMBnttranss
****************************************************************************/
-void reply_nttranss(connection_struct *conn, struct smb_request *req)
+void reply_nttranss(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
}
#endif /* O_SYNC */
- if (posix_open & (access_mask & FILE_APPEND_DATA)) {
+ if (posix_open && (access_mask & FILE_APPEND_DATA)) {
flags2 |= O_APPEND;
}
return NT_STATUS_OK;
}
-NTSTATUS create_directory(connection_struct *conn, const char *directory)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
{
NTSTATUS status;
SMB_STRUCT_STAT sbuf;
SET_STAT_INVALID(sbuf);
- status = open_directory(conn, NULL, directory, &sbuf,
+ status = open_directory(conn, req, directory, &sbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */
FILE_SHARE_NONE, /* Ignored for stat opens */
FILE_CREATE,
}
memset(result,'\0',smb_size);
- if (!srv_encryption_on()) {
- cli_set_message(result,8,0,true);
- } else {
- char inbuf[8];
- smb_set_enclen(inbuf,4,srv_enc_ctx());
- srv_set_message(inbuf,result,8,0,true);
- }
+ srv_set_message(result,8,0,true);
SCVAL(result,smb_com,SMBlockingX);
SSVAL(result,smb_tid,fsp->conn->cnum);
SSVAL(result,smb_pid,0xFFFF);
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
return;
}
- srv_set_message((const char *)req->inbuf,
- (char *)req->outbuf, 12, nread, False);
+ srv_set_message((char *)req->outbuf, 12, nread, False);
SSVAL(req->outbuf,smb_vwv5,nread);
SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
return &smb_read_error;
}
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
+{
+ size_t len;
+ size_t nwritten=0;
+ ssize_t ret;
+ char *buf_out = buffer;
+
+ /* Sign the outgoing packet if required. */
+ srv_calculate_sign_mac(buf_out);
+
+ if (do_encrypt) {
+ NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("send_smb: SMB encryption failed "
+ "on outgoing packet! Error %s\n",
+ nt_errstr(status) ));
+ return false;
+ }
+ }
+
+ len = smb_len(buf_out) + 4;
+
+ while (nwritten < len) {
+ ret = write_data(fd,buf_out+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ srv_free_enc_buffer(buf_out);
+ return false;
+ }
+ nwritten += ret;
+ }
+
+ srv_free_enc_buffer(buf_out);
+ return true;
+}
+
/*******************************************************************
Setup the word count and byte count for a smb message.
- copying the '0xFF X X X' bytes from incoming
- buffer (so we copy any encryption context).
********************************************************************/
-int srv_set_message(const char *frombuf,
- char *buf,
+int srv_set_message(char *buf,
int num_words,
int num_bytes,
bool zero)
}
SCVAL(buf,smb_wct,num_words);
SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
- _smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
- if (buf != frombuf) {
- memcpy(buf+4, frombuf+4, 4);
- }
+ smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
return (smb_size + num_words*2 + num_bytes);
}
-static bool valid_smb_header(const char *inbuf)
+static bool valid_smb_header(const uint8_t *inbuf)
{
- if (srv_encryption_on()) {
- uint16_t enc_num;
- NTSTATUS status = get_enc_ctx_num(inbuf, &enc_num);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
- return (enc_num == 0);
+ if (is_encrypted_packet(inbuf)) {
+ return true;
}
return (strncmp(smb_base(inbuf),"\377SMB",4) == 0);
}
(2*14) + /* word count (including bcc) */ \
1 /* pad byte */)
-ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
+static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
const char lenbuf[4],
int fd,
char **buffer,
* valid writeX call.
*/
- if (is_valid_writeX_buffer(writeX_header)) {
+ if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
/*
* If the data offset is beyond what
* we've read, drain the extra bytes.
return -1;
}
- if (CVAL(lenbuf,0) != SMBkeepalive &&
+ if (CVAL(lenbuf,0) == 0 &&
min_recv_size &&
smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */
!srv_is_signing_active()) {
return len + 4;
}
-ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
- unsigned int timeout, size_t *p_unread)
+static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx,
+ int fd,
+ char **buffer,
+ unsigned int timeout,
+ size_t *p_unread,
+ bool *p_encrypted)
{
ssize_t len;
+ *p_encrypted = false;
+
len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread);
if (len < 0) {
return -1;
}
- if (srv_encryption_on()) {
+ if (is_encrypted_packet((uint8_t *)*buffer)) {
NTSTATUS status = srv_decrypt_buffer(*buffer);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
SMB_READ_BAD_DECRYPT);
return -1;
}
+ *p_encrypted = true;
}
/* Check the incoming SMB signature. */
void init_smb_request(struct smb_request *req,
const uint8 *inbuf,
- size_t unread_bytes)
+ size_t unread_bytes,
+ bool encrypted)
{
size_t req_size = smb_len(inbuf) + 4;
/* Ensure we have at least smb_size bytes. */
req->tid = SVAL(inbuf, smb_tid);
req->wct = CVAL(inbuf, smb_wct);
req->unread_bytes = unread_bytes;
+ req->encrypted = encrypted;
+ req->conn = conn_find(req->tid);
/* Ensure we have at least wct words and 2 bytes of bcc. */
if (smb_size + req->wct*2 > req_size) {
msg->request_time = request_time;
msg->end_time = end_time;
+ msg->encrypted = req->encrypted;
if (private_data) {
msg->private_data = data_blob_talloc(msg, private_data,
char **buffer,
size_t *buffer_len,
int timeout,
- size_t *p_unread)
+ size_t *p_unread,
+ bool *p_encrypted)
{
fd_set r_fds, w_fds;
int selrtn;
return False;
}
*buffer_len = msg->buf.length;
+ *p_encrypted = msg->encrypted;
/* We leave this message on the queue so the open code can
know this is a retry. */
goto again;
}
- len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread);
+ len = receive_smb_talloc(mem_ctx, smbd_server_fd(),
+ buffer, 0, p_unread, p_encrypted);
if (len == -1) {
return False;
*/
static const struct smb_message_struct {
const char *name;
- void (*fn_new)(connection_struct *conn, struct smb_request *req);
+ void (*fn_new)(struct smb_request *req);
int flags;
} smb_messages[256] = {
}
construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
- srv_set_message((const char *)req->inbuf,
- (char *)req->outbuf, num_words, num_bytes, false);
+ srv_set_message((char *)req->outbuf, num_words, num_bytes, false);
/*
* Zero out the word area, the caller has to take care of the bcc area
* himself
find.
****************************************************************************/
-static void switch_message(uint8 type, struct smb_request *req, int size)
+static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
{
int flags;
uint16 session_tag;
- connection_struct *conn;
+ connection_struct *conn = NULL;
static uint16 last_session_tag = UID_FIELD_INVALID;
/* Make sure this is an SMB packet. smb_size contains NetBIOS header
* so subtract 4 from it. */
- if (!valid_smb_header((const char *)req->inbuf)
+ if (!valid_smb_header(req->inbuf)
|| (size < (smb_size - 4))) {
DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
smb_len(req->inbuf)));
DEBUG(0,("Unknown message type %d!\n",type));
smb_dump("Unknown", 1, (char *)req->inbuf, size);
reply_unknown_new(req, type);
- return;
+ return NULL;
}
flags = smb_messages[type].flags;
/* In share mode security we must ignore the vuid. */
session_tag = (lp_security() == SEC_SHARE)
? UID_FIELD_INVALID : req->vuid;
- conn = conn_find(req->tid);
+ conn = req->conn;
DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
(int)sys_getpid(), (unsigned long)conn));
} else {
reply_doserror(req, ERRSRV, ERRinvnid);
}
- return;
+ return NULL;
}
if (!change_to_user(conn,session_tag)) {
reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
- return;
+ return conn;
}
/* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
/* Does it need write permission? */
if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
- return;
+ return conn;
}
/* IPC services are limited */
if (IS_IPC(conn) && !(flags & CAN_IPC)) {
reply_doserror(req, ERRSRV,ERRaccess);
- return;
+ return conn;
}
} else {
/* This call needs to be run as root */
/* load service specific parameters */
if (conn) {
+ if (req->encrypted) {
+ conn->encrypted_tid = true;
+ /* encrypted required from now on. */
+ conn->encrypt_level = Required;
+ } else if (ENCRYPTION_REQUIRED(conn)) {
+ uint8 com = CVAL(req->inbuf,smb_com);
+ if (com != SMBtrans2 && com != SMBtranss2) {
+ exit_server_cleanly("encryption required "
+ "on connection");
+ return conn;
+ }
+ }
+
if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
(flags & (AS_USER|DO_CHDIR)
?True:False))) {
reply_doserror(req, ERRSRV, ERRaccess);
- return;
- }
-
- if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
- /* An encrypted packet has 0xFF 'E' at offset 4
- * which is little endian 0x45FF */
- uint8 com = CVAL(req->inbuf,smb_com);
- if (com != SMBtrans2 && com != SMBtranss2) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
+ return conn;
}
conn->num_smb_operations++;
}
!check_access(smbd_server_fd(), lp_hostsallow(-1),
lp_hostsdeny(-1)))) {
reply_doserror(req, ERRSRV, ERRaccess);
- return;
+ return conn;
}
- smb_messages[type].fn_new(conn, req);
+ smb_messages[type].fn_new(req);
+ return req->conn;
}
/****************************************************************************
Construct a reply to the incoming packet.
****************************************************************************/
-static void construct_reply(char *inbuf, int size, size_t unread_bytes)
+static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
{
uint8 type = CVAL(inbuf,smb_com);
+ connection_struct *conn;
struct smb_request *req;
chain_size = 0;
if (!(req = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req, (uint8 *)inbuf, unread_bytes);
+ init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
- switch_message(type, req, size);
+ conn = switch_message(type, req, size);
if (req->unread_bytes) {
/* writeX failed. drain socket. */
show_msg((char *)req->outbuf);
}
- if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) {
- exit_server_cleanly("construct_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
+ exit_server_cleanly("construct_reply: srv_send_smb failed.");
}
TALLOC_FREE(req);
Process an smb from the client
****************************************************************************/
-static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
+static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted)
{
static int trans_num;
int msg_type = CVAL(inbuf,0);
static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ( "Connection denied from %s\n",
client_addr(get_client_fd(),addr,sizeof(addr)) ) );
- (void)send_smb(smbd_server_fd(),(char *)buf);
+ (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
exit_server_cleanly("connection denied");
}
}
show_msg(inbuf);
- construct_reply(inbuf,nread,unread_bytes);
+ construct_reply(inbuf,nread,unread_bytes,encrypted);
trans_num++;
}
void construct_reply_common(const char *inbuf, char *outbuf)
{
- srv_set_message(inbuf,outbuf,0,0,false);
+ srv_set_message(outbuf,0,0,false);
SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
SIVAL(outbuf,smb_rcls,0);
if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req2, (uint8 *)inbuf2,0);
+ init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted);
/* process the request */
switch_message(smb_com2, req2, new_size);
int num_echos;
char *inbuf;
size_t inbuf_len;
+ bool encrypted = false;
TALLOC_CTX *frame = talloc_stackframe();
errno = 0;
run_events(smbd_event_context(), 0, NULL, NULL);
while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
- select_timeout, &unread_bytes)) {
+ select_timeout,
+ &unread_bytes,
+ &encrypted)) {
if(!timeout_processing(&select_timeout,
&last_timeout_processing_time))
return;
*/
num_echos = smb_echo_count;
- process_smb(inbuf, inbuf_len, unread_bytes);
+ process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
TALLOC_FREE(inbuf);
/*
* We only really use 4 bytes of the outbuf, but for the smb_setlen
- * calculation & friends (send_smb uses that) we need the full smb
+ * calculation & friends (srv_send_smb uses that) we need the full smb
* header.
*/
char outbuf[smb_size];
DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
msg_type, msg_flags));
- send_smb(smbd_server_fd(), outbuf);
+ srv_send_smb(smbd_server_fd(), outbuf, false);
return;
}
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tcon(connection_struct *conn, struct smb_request *req)
+void reply_tcon(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
const char *service;
char *service_buf = NULL;
char *password = NULL;
password_blob = data_blob(password, pwlen+1);
conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
+ req->conn = conn;
data_blob_clear_free(&password_blob);
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
+void reply_tcon_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *service = NULL;
DATA_BLOB password;
TALLOC_CTX *ctx = talloc_tos();
/* we might have to close an old one */
if ((tcon_flags & 0x1) && conn) {
close_cnum(conn,req->vuid);
+ req->conn = NULL;
+ conn = NULL;
}
if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
conn = make_connection(service, password, client_devicetype,
req->vuid, &nt_status);
+ req->conn =conn;
data_blob_clear_free(&password);
Reply to an unknown type.
****************************************************************************/
-int reply_unknown(char *inbuf,char *outbuf)
-{
- int type;
- type = CVAL(inbuf,smb_com);
-
- DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
- smb_fn_name(type), type, type));
-
- return(ERROR_DOS(ERRSRV,ERRunknownsmb));
-}
-
void reply_unknown_new(struct smb_request *req, uint8 type)
{
DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ioctl(connection_struct *conn, struct smb_request *req)
+void reply_ioctl(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint16 device;
uint16 function;
uint32 ioctl_code;
Reply to a checkpath.
****************************************************************************/
-void reply_checkpath(connection_struct *conn, struct smb_request *req)
+void reply_checkpath(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
Reply to a getatr.
****************************************************************************/
-void reply_getatr(connection_struct *conn, struct smb_request *req)
+void reply_getatr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
SMB_STRUCT_STAT sbuf;
int mode=0;
Reply to a setatr.
****************************************************************************/
-void reply_setatr(connection_struct *conn, struct smb_request *req)
+void reply_setatr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
int mode;
time_t mtime;
Reply to a dskattr.
****************************************************************************/
-void reply_dskattr(connection_struct *conn, struct smb_request *req)
+void reply_dskattr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT dfree,dsize,bsize;
START_PROFILE(SMBdskattr);
Can be called from SMBsearch, SMBffirst or SMBfunique.
****************************************************************************/
-void reply_search(connection_struct *conn, struct smb_request *req)
+void reply_search(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *mask = NULL;
char *directory = NULL;
char *fname = NULL;
Reply to a fclose (stop directory search).
****************************************************************************/
-void reply_fclose(connection_struct *conn, struct smb_request *req)
+void reply_fclose(struct smb_request *req)
{
int status_len;
char status[21];
Reply to an open.
****************************************************************************/
-void reply_open(connection_struct *conn, struct smb_request *req)
+void reply_open(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 fattr=0;
SMB_OFF_T size = 0;
Reply to an open and X.
****************************************************************************/
-void reply_open_and_X(connection_struct *conn, struct smb_request *req)
+void reply_open_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint16 open_flags;
int deny_mode;
/****************************************************************************
Reply to a SMBulogoffX.
- conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
+void reply_ulogoffX(struct smb_request *req)
{
user_struct *vuser;
Reply to a mknew or a create.
****************************************************************************/
-void reply_mknew(connection_struct *conn, struct smb_request *req)
+void reply_mknew(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
int com;
uint32 fattr = 0;
Reply to a create temporary file.
****************************************************************************/
-void reply_ctemp(connection_struct *conn, struct smb_request *req)
+void reply_ctemp(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 fattr;
files_struct *fsp;
Reply to a unlink
****************************************************************************/
-void reply_unlink(connection_struct *conn, struct smb_request *req)
+void reply_unlink(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
uint32 dirtype;
NTSTATUS status;
Reply to a readbraw (core+ protocol).
****************************************************************************/
-void reply_readbraw(connection_struct *conn, struct smb_request *req)
+void reply_readbraw(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t maxcount,mincount;
size_t nread = 0;
SMB_OFF_T startpos;
START_PROFILE(SMBreadbraw);
- if (srv_is_signing_active() || srv_encryption_on()) {
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
"raw reads/writes are disallowed.");
}
Reply to a lockread (core+ protocol).
****************************************************************************/
-void reply_lockread(connection_struct *conn, struct smb_request *req)
+void reply_lockread(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t nread = -1;
char *data;
SMB_OFF_T startpos;
return;
}
- srv_set_message((const char *)req->inbuf,
- (char *)req->outbuf, 5, nread+3, False);
+ srv_set_message((char *)req->outbuf, 5, nread+3, False);
SSVAL(req->outbuf,smb_vwv0,nread);
SSVAL(req->outbuf,smb_vwv5,nread+3);
Reply to a read.
****************************************************************************/
-void reply_read(connection_struct *conn, struct smb_request *req)
+void reply_read(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtoread;
ssize_t nread = 0;
char *data;
return;
}
- srv_set_message((const char *)req->inbuf,
- (char *)req->outbuf, 5, nread+3, False);
+ srv_set_message((char *)req->outbuf, 5, nread+3, False);
SSVAL(req->outbuf,smb_vwv0,nread);
SSVAL(req->outbuf,smb_vwv5,nread+3);
Setup readX header.
****************************************************************************/
-static int setup_readX_header(const char *inbuf, char *outbuf, size_t smb_maxcnt)
+static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
{
int outsize;
char *data;
- outsize = srv_set_message(inbuf, outbuf,12,smb_maxcnt,False);
+ outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
data = smb_buf(outbuf);
memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
*/
if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
+ !is_encrypted_packet(req->inbuf) &&
lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
header = data_blob_const(headerbuf, sizeof(headerbuf));
construct_reply_common((char *)req->inbuf, (char *)headerbuf);
- setup_readX_header((const char *)req->inbuf,
- (char *)headerbuf, smb_maxcnt);
+ setup_readX_header((char *)headerbuf, smb_maxcnt);
if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
uint8 headerbuf[smb_size + 2*12];
construct_reply_common((char *)req->inbuf, (char *)headerbuf);
- setup_readX_header((const char *)req->inbuf,
- (char *)headerbuf, smb_maxcnt);
+ setup_readX_header((char *)headerbuf, smb_maxcnt);
/* Send out the header. */
if (write_data(smbd_server_fd(), (char *)headerbuf,
return;
}
- setup_readX_header((const char *)req->inbuf,
- (char *)req->outbuf, nread);
+ setup_readX_header((char *)req->outbuf, nread);
DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
fsp->fnum, (int)smb_maxcnt, (int)nread ) );
Reply to a read and X.
****************************************************************************/
-void reply_read_and_X(connection_struct *conn, struct smb_request *req)
+void reply_read_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
SMB_OFF_T startpos;
size_t smb_maxcnt;
return;
}
/* We currently don't do this on signed or sealed data. */
- if (srv_is_signing_active() || srv_encryption_on()) {
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
Reply to a writebraw (core+ or LANMAN1.0 protocol).
****************************************************************************/
-void reply_writebraw(connection_struct *conn, struct smb_request *req)
+void reply_writebraw(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int outsize = 0;
char *buf = NULL;
ssize_t nwritten=0;
* it to send more bytes */
memcpy(buf, req->inbuf, smb_size);
- outsize = srv_set_message((const char *)req->inbuf, buf,
+ outsize = srv_set_message(buf,
Protocol>PROTOCOL_COREPLUS?1:0,0,True);
SCVAL(buf,smb_com,SMBwritebraw);
SSVALS(buf,smb_vwv0,0xFFFF);
show_msg(buf);
- if (!send_smb(smbd_server_fd(),buf)) {
- exit_server_cleanly("reply_writebraw: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),
+ buf,
+ IS_CONN_ENCRYPTED(conn))) {
+ exit_server_cleanly("reply_writebraw: srv_send_smb "
"failed.");
}
Reply to a writeunlock (core+).
****************************************************************************/
-void reply_writeunlock(connection_struct *conn, struct smb_request *req)
+void reply_writeunlock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t nwritten = -1;
size_t numtowrite;
SMB_OFF_T startpos;
Reply to a write.
****************************************************************************/
-void reply_write(connection_struct *conn, struct smb_request *req)
+void reply_write(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtowrite;
ssize_t nwritten = -1;
SMB_OFF_T startpos;
(2*14) + /* word count (including bcc) */ \
1 /* pad byte */)
-bool is_valid_writeX_buffer(const char *inbuf)
+bool is_valid_writeX_buffer(const uint8_t *inbuf)
{
size_t numtowrite;
connection_struct *conn = NULL;
unsigned int doff = 0;
size_t len = smb_len_large(inbuf);
- if (srv_encryption_on()) {
+ if (is_encrypted_packet(inbuf)) {
/* Can't do this on encrypted
* connections. */
return false;
Reply to a write and X.
****************************************************************************/
-void reply_write_and_X(connection_struct *conn, struct smb_request *req)
+void reply_write_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
SMB_OFF_T startpos;
size_t numtowrite;
Reply to a lseek.
****************************************************************************/
-void reply_lseek(connection_struct *conn, struct smb_request *req)
+void reply_lseek(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_OFF_T startpos;
SMB_OFF_T res= -1;
int mode,umode;
Reply to a flush.
****************************************************************************/
-void reply_flush(connection_struct *conn, struct smb_request *req)
+void reply_flush(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint16 fnum;
files_struct *fsp;
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_exit(connection_struct *conn, struct smb_request *req)
+void reply_exit(struct smb_request *req)
{
START_PROFILE(SMBexit);
Reply to a close - has to deal with closing a directory opened by NT SMB's.
****************************************************************************/
-void reply_close(connection_struct *conn, struct smb_request *req)
+void reply_close(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
Reply to a writeclose (Core+ protocol).
****************************************************************************/
-void reply_writeclose(connection_struct *conn, struct smb_request *req)
+void reply_writeclose(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtowrite;
ssize_t nwritten = -1;
NTSTATUS close_status = NT_STATUS_OK;
Reply to a lock.
****************************************************************************/
-void reply_lock(connection_struct *conn, struct smb_request *req)
+void reply_lock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp;
Reply to a unlock.
****************************************************************************/
-void reply_unlock(connection_struct *conn, struct smb_request *req)
+void reply_unlock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp;
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tdis(connection_struct *conn, struct smb_request *req)
+void reply_tdis(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
START_PROFILE(SMBtdis);
if (!conn) {
conn->used = False;
close_cnum(conn,req->vuid);
+ req->conn = NULL;
reply_outbuf(req, 0, 0);
END_PROFILE(SMBtdis);
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_echo(connection_struct *conn, struct smb_request *req)
+void reply_echo(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int smb_reverb;
int seq_num;
unsigned int data_len = smb_buflen(req->inbuf);
SSVAL(req->outbuf,smb_vwv0,seq_num);
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("reply_echo: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)||req->encrypted))
+ exit_server_cleanly("reply_echo: srv_send_smb failed.");
}
DEBUG(3,("echo %d times\n", smb_reverb));
Reply to a printopen.
****************************************************************************/
-void reply_printopen(connection_struct *conn, struct smb_request *req)
+void reply_printopen(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
NTSTATUS status;
Reply to a printclose.
****************************************************************************/
-void reply_printclose(connection_struct *conn, struct smb_request *req)
+void reply_printclose(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
NTSTATUS status;
Reply to a printqueue.
****************************************************************************/
-void reply_printqueue(connection_struct *conn, struct smb_request *req)
+void reply_printqueue(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int max_count;
int start_index;
Reply to a printwrite.
****************************************************************************/
-void reply_printwrite(connection_struct *conn, struct smb_request *req)
+void reply_printwrite(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int numtowrite;
char *data;
files_struct *fsp;
Reply to a mkdir.
****************************************************************************/
-void reply_mkdir(connection_struct *conn, struct smb_request *req)
+void reply_mkdir(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *directory = NULL;
NTSTATUS status;
SMB_STRUCT_STAT sbuf;
return;
}
- status = create_directory(conn, directory);
+ status = create_directory(conn, req, directory);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
Reply to a rmdir.
****************************************************************************/
-void reply_rmdir(connection_struct *conn, struct smb_request *req)
+void reply_rmdir(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *directory = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
Reply to a mv.
****************************************************************************/
-void reply_mv(connection_struct *conn, struct smb_request *req)
+void reply_mv(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
char *newname = NULL;
char *p;
Reply to a file copy.
****************************************************************************/
-void reply_copy(connection_struct *conn, struct smb_request *req)
+void reply_copy(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
char *newname = NULL;
char *directory = NULL;
Reply to a lockingX request.
****************************************************************************/
-void reply_lockingX(connection_struct *conn, struct smb_request *req)
+void reply_lockingX(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
unsigned char locktype;
unsigned char oplocklevel;
* onto the blocking lock queue.
*/
if(push_blocking_lock_request(br_lck,
- (char *)req->inbuf,
- smb_len(req->inbuf)+4,
+ req,
fsp,
lock_timeout,
i,
please contact vl@samba.org
****************************************************************************/
-void reply_readbmpx(connection_struct *conn, struct smb_request *req)
+void reply_readbmpx(struct smb_request *req)
{
START_PROFILE(SMBreadBmpx);
reply_doserror(req, ERRSRV, ERRuseSTD);
please contact vl@samba.org
****************************************************************************/
-void reply_readbs(connection_struct *conn, struct smb_request *req)
+void reply_readbs(struct smb_request *req)
{
START_PROFILE(SMBreadBs);
reply_doserror(req, ERRSRV, ERRuseSTD);
Reply to a SMBsetattrE.
****************************************************************************/
-void reply_setattrE(connection_struct *conn, struct smb_request *req)
+void reply_setattrE(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
struct timespec ts[2];
files_struct *fsp;
please contact vl@samba.org
****************************************************************************/
-void reply_writebmpx(connection_struct *conn, struct smb_request *req)
+void reply_writebmpx(struct smb_request *req)
{
START_PROFILE(SMBwriteBmpx);
reply_doserror(req, ERRSRV, ERRuseSTD);
please contact vl@samba.org
****************************************************************************/
-void reply_writebs(connection_struct *conn, struct smb_request *req)
+void reply_writebs(struct smb_request *req)
{
START_PROFILE(SMBwriteBs);
reply_doserror(req, ERRSRV, ERRuseSTD);
Reply to a SMBgetattrE.
****************************************************************************/
-void reply_getattrE(connection_struct *conn, struct smb_request *req)
+void reply_getattrE(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx;
/******************************************************************************
- Is server encryption on ?
+ Return global enc context - this must change if we ever do multiple contexts.
******************************************************************************/
-bool srv_encryption_on(void)
+uint16_t srv_enc_ctx(void)
{
- if (srv_trans_enc_ctx) {
- return common_encryption_on(srv_trans_enc_ctx->es);
- }
- return false;
+ return srv_trans_enc_ctx->es->enc_ctx_num;
}
/******************************************************************************
- Return global enc context - this must change if we ever do multiple contexts.
+ Is this an incoming encrypted packet ?
******************************************************************************/
-uint16 srv_enc_ctx(void)
+bool is_encrypted_packet(const uint8_t *inbuf)
{
- return srv_trans_enc_ctx->es->enc_ctx_num;
+ NTSTATUS status;
+ uint16_t enc_num;
+
+ /* Ignore non-session messages. */
+ if(CVAL(inbuf,0)) {
+ return false;
+ }
+
+ status = get_enc_ctx_num(inbuf, &enc_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) {
+ return true;
+ }
+ return false;
}
/******************************************************************************
{
/* We know this is an smb buffer, and we
* didn't malloc, only copy, for a keepalive,
- * so ignore session keepalives. */
+ * so ignore non-session messages. */
- if(CVAL(buf,0) == SMBkeepalive) {
+ if(CVAL(buf,0)) {
return;
}
NTSTATUS srv_decrypt_buffer(char *buf)
{
- /* Ignore session keepalives. */
- if(CVAL(buf,0) == SMBkeepalive) {
+ /* Ignore non-session messages. */
+ if(CVAL(buf,0)) {
return NT_STATUS_OK;
}
{
*buf_out = buf;
- /* Ignore session keepalives. */
- if(CVAL(buf,0) == SMBkeepalive) {
+ /* Ignore non-session messages. */
+ if(CVAL(buf,0)) {
return NT_STATUS_OK;
}
srv_trans_enc_ctx->es->enc_on = true;
partial_srv_trans_enc_ctx = NULL;
+
return NT_STATUS_OK;
}
Send a security blob via a session setup reply.
****************************************************************************/
-static void reply_sesssetup_blob(connection_struct *conn,
- struct smb_request *req,
+static void reply_sesssetup_blob(struct smb_request *req,
DATA_BLOB blob,
NTSTATUS nt_status)
{
}
show_msg((char *)req->outbuf);
- send_smb(smbd_server_fd(),(char *)req->outbuf);
+ srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
TALLOC_FREE(req->outbuf);
}
Reply to a session setup spnego negotiate packet for kerberos.
****************************************************************************/
-static void reply_spnego_kerberos(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_kerberos(struct smb_request *req,
DATA_BLOB *secblob,
uint16 vuid,
bool *p_invalidate_vuid)
}
}
- server_info->was_mapped |= username_was_mapped;
+ if (username_was_mapped) {
+ server_info->was_mapped = username_was_mapped;
+ }
/* we need to build the token for the user. make_server_info_guest()
already does this */
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, req, response, ret);
+ reply_sesssetup_blob(req, response, ret);
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
leg of the NTLM auth steps.
***************************************************************************/
-static void reply_spnego_ntlmssp(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_ntlmssp(struct smb_request *req,
uint16 vuid,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
response = *ntlmssp_blob;
}
- reply_sesssetup_blob(conn, req, response, nt_status);
+ reply_sesssetup_blob(req, response, nt_status);
if (wrap) {
data_blob_free(&response);
}
Reply to a session setup spnego negotiate packet.
****************************************************************************/
-static void reply_spnego_negotiate(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_negotiate(struct smb_request *req,
uint16 vuid,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
lp_use_kerberos_keytab()) ) {
bool destroy_vuid = True;
- reply_spnego_kerberos(conn, req, &secblob, vuid,
+ reply_spnego_kerberos(req, &secblob, vuid,
&destroy_vuid);
data_blob_free(&secblob);
if (destroy_vuid) {
data_blob_free(&secblob);
- reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state,
+ reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
&chal, status, True);
data_blob_free(&chal);
Reply to a session setup spnego auth packet.
****************************************************************************/
-static void reply_spnego_auth(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_auth(struct smb_request *req,
uint16 vuid,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
lp_use_kerberos_keytab()) ) {
bool destroy_vuid = True;
- reply_spnego_kerberos(conn, req, &secblob,
+ reply_spnego_kerberos(req, &secblob,
vuid, &destroy_vuid);
data_blob_free(&secblob);
data_blob_free(&auth);
data_blob_free(&auth);
- reply_spnego_ntlmssp(conn, req, vuid,
+ reply_spnego_ntlmssp(req, vuid,
auth_ntlmssp_state,
&auth_reply, status, True);
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-static void reply_sesssetup_and_X_spnego(connection_struct *conn,
- struct smb_request *req)
+static void reply_sesssetup_and_X_spnego(struct smb_request *req)
{
uint8 *p;
DATA_BLOB blob1;
/* its a negTokenTarg packet */
- reply_spnego_negotiate(conn, req, vuid, blob1,
+ reply_spnego_negotiate(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
/* its a auth packet */
- reply_spnego_auth(conn, req, vuid, blob1,
+ reply_spnego_auth(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
data_blob_free(&blob1);
- reply_spnego_ntlmssp(conn, req, vuid,
+ reply_spnego_ntlmssp(req, vuid,
&vuser->auth_ntlmssp_state,
&chal, status, False);
data_blob_free(&chal);
Reply to a session setup command.
****************************************************************************/
-void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
+void reply_sesssetup_and_X(struct smb_request *req)
{
int sess_vuid;
int smb_bufsize;
setup_new_vc_session();
}
- reply_sesssetup_and_X_spnego(conn, req);
+ reply_sesssetup_and_X_spnego(req);
END_PROFILE(SMBsesssetupX);
return;
}
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-void send_trans2_replies(struct smb_request *req,
+void send_trans2_replies(connection_struct *conn,
+ struct smb_request *req,
const char *params,
int paramsize,
const char *pdata,
/* Send the packet */
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("send_trans2_replies: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
TALLOC_FREE(req->outbuf);
}
/* Send the required number of replies */
- send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
}
/*********************************************************
SSVAL(params,6,0); /* Never an EA error */
SSVAL(params,8,last_entry_off);
- send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
+ send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
if ((! *directory) && dptr_path(dptr_num)) {
SSVAL(params,4,0); /* Never an EA error */
SSVAL(params,6,last_entry_off);
- send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
+ send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
return;
info_level = SVAL(params,0);
- if (IS_IPC(conn) ||
- (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF )) {
+ if (IS_IPC(conn)) {
+ if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+ DEBUG(0,("call_trans2qfsinfo: not an allowed "
+ "info level (0x%x) on IPC$.\n",
+ (unsigned int)info_level));
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+ }
+
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
DEBUG(0,("call_trans2qfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ exit_server_cleanly("encryption required "
+ "on connection");
return;
}
}
}
- send_trans2_replies(req, params, 0, pdata, data_len,
+ send_trans2_replies(conn, req, params, 0, pdata, data_len,
max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n",
}
}
- if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
DEBUG(0,("call_trans2setfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ exit_server_cleanly("encryption required "
+ "on connection");
return;
}
}
return;
}
- send_trans2_replies(req,
+ send_trans2_replies(conn, req,
*pparams,
param_len,
*ppdata,
return;
}
- send_trans2_replies(req, params, param_size, *ppdata, data_size,
+ send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
max_data_bytes);
return;
return;
}
- send_trans2_replies(req, params, param_size, *ppdata, data_size,
+ send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
max_data_bytes);
return;
****************************************************************************/
static NTSTATUS smb_set_posix_lock(connection_struct *conn,
- const uint8 *inbuf,
- int length,
+ const struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp)
uint32 lock_pid;
bool blocking_lock = False;
enum brl_type lock_type;
+
NTSTATUS status = NT_STATUS_OK;
if (fsp == NULL || fsp->fh->fd == -1) {
* onto the blocking lock queue.
*/
if(push_blocking_lock_request(br_lck,
- (char *)inbuf, length,
+ req,
fsp,
-1, /* infinite timeout. */
0,
DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2,
+ send_trans2_replies(conn, req, params, 2,
*ppdata, 0,
max_data_bytes);
return;
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
- status = smb_set_posix_lock(conn, req->inbuf,
- smb_len(req->inbuf) + 4,
+ status = smb_set_posix_lock(conn, req,
pdata, total_data, fsp);
break;
}
}
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2, *ppdata, data_return_size,
+ send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
max_data_bytes);
return;
return;
}
- status = create_directory(conn, directory);
+ status = create_directory(conn, req, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
return;
}
if(fnf_handle == 0)
fnf_handle = 257;
- send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
return;
}
SSVAL(params,0,0); /* No changes */
SSVAL(params,2,0); /* No EA errors */
- send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
return;
}
SSVAL(req->inbuf, smb_flg2,
SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
- send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
+ send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
return;
}
srvstr_push(pdata, req->flags2, pdata+18,
lp_servicename(SNUM(conn)), 13,
STR_ASCII|STR_TERMINATE); /* Service name */
- send_trans2_replies(req, *pparams, 0, *ppdata, 32,
+ send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
max_data_bytes);
return;
}
Reply to a SMBfindclose (stop trans2 directory search).
****************************************************************************/
-void reply_findclose(connection_struct *conn, struct smb_request *req)
+void reply_findclose(struct smb_request *req)
{
int dptr_num;
Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
****************************************************************************/
-void reply_findnclose(connection_struct *conn, struct smb_request *req)
+void reply_findnclose(struct smb_request *req)
{
int dptr_num;
SSVAL(req->inbuf,smb_flg2,req->flags2);
}
- if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
+ if (conn->encrypt_level == Required && !req->encrypted) {
if (state->call != TRANSACT2_QFSINFO &&
state->call != TRANSACT2_SETFSINFO) {
DEBUG(0,("handle_trans2: encryption required "
Reply to a SMBtrans2.
****************************************************************************/
-void reply_trans2(connection_struct *conn, struct smb_request *req)
+void reply_trans2(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int dsoff;
unsigned int dscnt;
unsigned int psoff;
Reply to a SMBtranss2
****************************************************************************/
-void reply_transs2(connection_struct *conn, struct smb_request *req)
+void reply_transs2(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
int size;
static bool use_kerberos;
static fstring multishare_conn_fname;
static bool use_multishare_conn = False;
+static bool do_encrypt;
bool torture_showall = False;
return ret;
}
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+static bool force_cli_encryption(struct cli_state *c,
+ const char *sharename)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+ NTSTATUS status;
+
+ if (!SERVER_HAS_UNIX_CIFS(c)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ return false;
+ }
+
+ if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ return false;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", sharename);
+ return false;
+ }
+
+ if (c->use_kerberos) {
+ status = cli_gss_smb_encryption_start(c);
+ } else {
+ status = cli_raw_ntlm_smb_encryption_start(c,
+ username,
+ password,
+ workgroup);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ return true;
+}
+
static struct cli_state *open_nbt_connection(void)
{
if (use_level_II_oplocks) (*c)->use_level_II_oplocks = True;
(*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
+ if (do_encrypt) {
+ return force_cli_encryption(*c,
+ sharename);
+ }
return True;
}
fstrcpy(workgroup, lp_workgroup());
- while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Ac:ks:b:")) != EOF) {
+ while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Aec:ks:b:")) != EOF) {
switch (opt) {
case 'p':
port_to_use = atoi(optarg);
case 'c':
client_txt = optarg;
break;
+ case 'e':
+ do_encrypt = true;
+ break;
case 'k':
#ifdef HAVE_KRB5
use_kerberos = True;
int opt_have_ip = False;
struct sockaddr_storage opt_dest_ip;
+bool smb_encrypt;
extern bool AllowDebugChange;
service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
- if (NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- } else {
+ if (!NT_STATUS_IS_OK(nt_status)) {
d_fprintf(stderr, "Could not connect to server %s\n", server_name);
/* Display a nicer message depending on the result */
if (NT_STATUS_V(nt_status) ==
NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED))
d_fprintf(stderr, "The account was disabled.\n");
-
return nt_status;
}
+
+ if (smb_encrypt) {
+ nt_status = cli_force_encryption(*c,
+ opt_user_name,
+ opt_password,
+ opt_workgroup);
+
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_SUPPORTED)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNKNOWN_REVISION)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", service_name);
+ } else if (!NT_STATUS_IS_OK(nt_status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(nt_status));
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(*c);
+ *c = NULL;
+ }
+ }
+
+ return nt_status;
}
/****************************************************************************
SAFE_FREE(user_and_realm);
- if (NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- } else {
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status)));
return nt_status;
}
+
+ if (smb_encrypt) {
+ nt_status = cli_cm_force_encryption(*c,
+ user_and_realm,
+ opt_password,
+ opt_workgroup,
+ "IPC$");
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(*c);
+ *c = NULL;
+ }
+ }
+
+ return nt_status;
}
/**
{"port", 'p', POPT_ARG_INT, &opt_port},
{"myname", 'n', POPT_ARG_STRING, &opt_requester_name},
{"server", 'S', POPT_ARG_STRING, &opt_host},
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
{"container", 'c', POPT_ARG_STRING, &opt_container},
{"comment", 'C', POPT_ARG_STRING, &opt_comment},
{"maxusers", 'M', POPT_ARG_INT, &opt_maxusers},
{"acls", 0, POPT_ARG_NONE, &opt_acls},
{"attrs", 0, POPT_ARG_NONE, &opt_attrs},
{"timestamps", 0, POPT_ARG_NONE, &opt_timestamps},
- {"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
+ {"exclude", 'X', POPT_ARG_STRING, &opt_exclude},
{"destination", 0, POPT_ARG_STRING, &opt_destination},
{"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report},
net_help(argc, argv);
exit(0);
break;
+ case 'e':
+ smb_encrypt=true;
+ break;
case 'I':
if (!interpret_string_addr(&opt_dest_ip,
poptGetOptArg(pc), 0)) {
*/
/*
- * This is an interface to the configuration stored inside the
- * samba registry. In the future there might be support for other
- * configuration backends as well.
+ * This is an interface to Samba's configuration as made available
+ * by the libnet_conf interface (source/libnet/libnet_conf.c).
+ *
+ * This currently supports local interaction with the configuration
+ * stored in the registry. But other backends and remote access via
+ * rpc might get implemented in the future.
*/
#include "includes.h"
d_printf("USAGE: net conf import [--test|-T] <filename> "
"[<servicename>]\n"
"\t[--test|-T] testmode - do not act, just print "
- "what would be done\n"
+ "what would be done\n"
"\t<servicename> only import service <servicename>, "
- "ignore the rest\n");
+ "ignore the rest\n");
return -1;
}
valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(bool *)ptr));
break;
case P_ENUM:
- for (i = 0; parm->enum_list[i].name; i++) {
- if (*(int *)ptr == parm->enum_list[i].value)
+ for (i = 0; parm->enum_list[i].name; i++) {
+ if (*(int *)ptr == parm->enum_list[i].value)
{
valstr = talloc_asprintf(ctx, "%s",
- parm->enum_list[i].name);
- break;
- }
- }
+ parm->enum_list[i].name);
+ break;
+ }
+ }
break;
case P_OCTAL: {
char *o = octal_string(*(int *)ptr);
param = strdup_lower(argv[1]);
value_str = argv[2];
+ if (!libnet_conf_share_exists(service)) {
+ werr = libnet_conf_create_share(service);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error creating share '%s': %s\n",
+ service, dos_errstr(werr));
+ goto done;
+ }
+ }
+
werr = libnet_conf_set_parameter(service, param, value_str);
if (!W_ERROR_IS_OK(werr)) {
{"import", net_conf_import,
"Import configuration from file in smb.conf format."},
{"listshares", net_conf_listshares,
- "List the registry shares."},
+ "List the share names."},
{"drop", net_conf_drop,
- "Delete the complete configuration from registry."},
+ "Delete the complete configuration."},
{"showshare", net_conf_showshare,
- "Show the definition of a registry share."},
+ "Show the definition of a share."},
{"addshare", net_conf_addshare,
- "Create a new registry share."},
+ "Create a new share."},
{"delshare", net_conf_delshare,
- "Delete a registry share."},
+ "Delete a share."},
{"setparm", net_conf_setparm,
"Store a parameter."},
{"getparm", net_conf_getparm,
ret = net_run_function2(argc, argv, "net conf", func);
- regdb_close();
-
-done:
return ret;
}
d_printf("\t-l or --long\t\t\tDisplay full information\n");
d_printf("\t-V or --version\t\t\tPrint samba version information\n");
d_printf("\t-P or --machine-pass\t\tAuthenticate as machine account\n");
+ d_printf("\t-e or --encrypt\t\tEncrypt SMB transport (UNIX extended servers only)\n");
return -1;
}
*******************************************************/
static struct cli_state *connect_one(const char *server, const char *share)
{
- struct cli_state *c;
+ struct cli_state *c = NULL;
struct sockaddr_storage ss;
NTSTATUS nt_status;
zero_addr(&ss);
}
}
- if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
- &ss, 0,
- share, "?????",
- get_cmdline_auth_info_username(),
- lp_workgroup(),
- get_cmdline_auth_info_password(),
- 0,
- get_cmdline_auth_info_signing_state(),
- NULL))) {
- return c;
- } else {
+ nt_status = cli_full_connection(&c, global_myname(), server,
+ &ss, 0,
+ share, "?????",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+ get_cmdline_auth_info_signing_state(),
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
return NULL;
}
+
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(c,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ share);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(c);
+ c = NULL;
+ }
+ }
+
+ return c;
}
/****************************************************************************
}
}
- if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
- &ss, 0,
- share, "?????",
- get_cmdline_auth_info_username(),
- lp_workgroup(),
- get_cmdline_auth_info_password(),
- 0,
- get_cmdline_auth_info_signing_state(),
- NULL))) {
- return c;
- } else {
+ nt_status = cli_full_connection(&c, global_myname(), server,
+ &ss, 0,
+ share, "?????",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ 0,
+ get_cmdline_auth_info_signing_state(),
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
return NULL;
}
+
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(c,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ share);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(c);
+ return NULL;
+ }
+ }
+
+ return c;
}
/****************************************************************************
}
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+static bool send_smb(int fd, char *buffer)
+{
+ size_t len;
+ size_t nwritten=0;
+ ssize_t ret;
+
+ len = smb_len(buffer) + 4;
+
+ while (nwritten < len) {
+ ret = write_data(fd,buffer+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ return false;
+ }
+ nwritten += ret;
+ }
+
+ return true;
+}
static void filter_child(int c, struct sockaddr_storage *dest_ss)
{
if (num <= 0) continue;
if (c != -1 && FD_ISSET(c, &fds)) {
- if (!receive_smb(c, packet, 0, NULL)) {
+ if (!receive_smb_raw(c, packet, 0, 0, NULL)) {
d_printf("client closed connection\n");
exit(0);
}
}
}
if (s != -1 && FD_ISSET(s, &fds)) {
- if (!receive_smb(s, packet, 0, NULL)) {
+ if (!receive_smb_raw(s, packet, 0, 0, NULL)) {
d_printf("server closed connection\n");
exit(0);
}
int c = 0;
const char *file = NULL;
char *rcfile = NULL;
+ bool smb_encrypt = false;
TALLOC_CTX *frame = talloc_stackframe();
struct poptOption long_options[] = {
{"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
{"resume", 'r', POPT_ARG_NONE, &_resume, 0, "Automatically resume aborted files" },
{"recursive", 'R', POPT_ARG_NONE, &_recursive, 0, "Recursively download files" },
{"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },
case 'a':
username = ""; password = "";
break;
+ case 'e':
+ smb_encrypt = true;
+ break;
}
}
return 1;
}
+ if (smb_encrypt) {
+ SMBCCTX *smb_ctx = smbc_set_context(NULL);
+ smbc_option_set(smb_ctx,
+ CONST_DISCARD(char *, "smb_encrypt_level"),
+ "require");
+ }
+
columns = get_num_cols();
total_start_time = time(NULL);
d.domain_type = domains[i].trust_type;
d.domain_trust_attribs = domains[i].trust_attributes;
} else {
+ /* Look up the record in the cache */
+ struct winbindd_tdc_domain *parent;
+
DEBUG(10,("trusted_domains(ads): Inheriting trust "
"flags for domain %s\n", d.alt_name));
+
+ parent = wcache_tdc_fetch_domain(NULL, domain->name);
+ if (parent) {
+ d.domain_flags = parent->trust_flags;
+ d.domain_type = parent->trust_type;
+ d.domain_trust_attribs = parent->trust_attribs;
+ } else {
d.domain_flags = domain->domain_flags;
d.domain_type = domain->domain_type;
d.domain_trust_attribs = domain->domain_trust_attribs;
}
+ TALLOC_FREE(parent);
+ }
wcache_tdc_add_domain( &d );
orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
- werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
+ if (our_domain->active_directory) {
+ struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL;
+
+ werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ NULL,
+ NULL,
+ DS_RETURN_DNS_NAME,
+ &domain_info);
+ if (W_ERROR_IS_OK(werr)) {
+ fstrcpy(tmp, domain_info->domain_controller_name);
+ if (strlen(domain->alt_name) == 0) {
+ fstrcpy(domain->alt_name,
+ CONST_DISCARD(char*, domain_info->domain_name));
+ }
+ if (strlen(domain->forest_name) == 0) {
+ fstrcpy(domain->forest_name,
+ CONST_DISCARD(char*, domain_info->dns_forest_name));
+ }
+ }
+ } else {
+
+ werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx,
+ our_domain->dcname,
domain->name, &tmp);
+ }
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
if (dns_name)
fstrcpy(domain->alt_name, dns_name);
- if ( forest_name )
+ /* See if we can set some domain trust flags about
+ ourself */
+
+ if ( forest_name ) {
fstrcpy(domain->forest_name, forest_name);
+ if (strequal(domain->forest_name, domain->alt_name)) {
+ domain->domain_flags = DS_DOMAIN_TREE_ROOT;
+ }
+ }
+
if (dom_sid)
sid_copy(&domain->sid, dom_sid);
} else {
s->username = talloc_strdup( state->mem_ctx, state->request.data.username );
}
- /* Get info for the domain */
+ /* Get info for the domain (either by short domain name or
+ DNS name in the case of a UPN) */
s->domain = find_domain_from_name_noinit(s->domname);
+ if (!s->domain) {
+ char *p = strchr(s->username, '@');
+
+ if (p) {
+ s->domain = find_domain_from_name_noinit(p+1);
+ }
+
+ }
if (s->domain == NULL) {
DEBUG(7, ("could not find domain entry for domain %s\n",
return NT_STATUS_OK;
}
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
/* no cache; hit the wire */
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
return;
- /* clear the TRUSTDOM cache first */
-
- wcache_tdc_clear();
+ /* I use to clear the cache here and start over but that
+ caused problems in child processes that needed the
+ trust dom list early on. Removing it means we
+ could have some trusted domains listed that have been
+ removed from our primary domain's DC until a full
+ restart. This should be ok since I think this is what
+ Windows does as well. */
/* this will only add new domains we didn't already know about
in the domain_list()*/