From 37aff885a62cdc5c3298e6f44165f9d9a22729c5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 19 Mar 2009 12:30:26 +0100 Subject: s3-spoolss: implement _spoolss_GetPrinterDriver2 level 101 (Bug #5140). Guenther --- source3/rpc_server/srv_spoolss_nt.c | 243 +++++++++++++++++++++++++++++++++++- 1 file changed, 238 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 15c137a88c..7bb0571042 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -4889,6 +4889,174 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx, return WERR_OK; } +/******************************************************************** + ********************************************************************/ + +static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx, + struct spoolss_DriverFileInfo *r, + const char *cservername, + const char *file_name, + enum spoolss_DriverFileType file_type, + uint32_t file_version) +{ + r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s", + cservername, file_name); + W_ERROR_HAVE_NO_MEMORY(r->file_name); + r->file_type = file_type; + r->file_version = file_version; + + return WERR_OK; +} + +/******************************************************************** + ********************************************************************/ + +static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx, + const NT_PRINTER_DRIVER_INFO_LEVEL *driver, + const char *cservername, + struct spoolss_DriverFileInfo **info_p, + uint32_t *count_p) +{ + struct spoolss_DriverFileInfo *info = NULL; + uint32_t count = 0; + WERROR result; + uint32_t i; + + *info_p = NULL; + *count_p = 0; + + if (strlen(driver->info_3->driverpath)) { + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + struct spoolss_DriverFileInfo, + count + 1); + W_ERROR_HAVE_NO_MEMORY(info); + result = fill_spoolss_DriverFileInfo(info, + &info[count], + cservername, + driver->info_3->driverpath, + SPOOLSS_DRIVER_FILE_TYPE_RENDERING, + 0); + W_ERROR_NOT_OK_RETURN(result); + count++; + } + + if (strlen(driver->info_3->configfile)) { + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + struct spoolss_DriverFileInfo, + count + 1); + W_ERROR_HAVE_NO_MEMORY(info); + result = fill_spoolss_DriverFileInfo(info, + &info[count], + cservername, + driver->info_3->configfile, + SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION, + 0); + W_ERROR_NOT_OK_RETURN(result); + count++; + } + + if (strlen(driver->info_3->datafile)) { + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + struct spoolss_DriverFileInfo, + count + 1); + W_ERROR_HAVE_NO_MEMORY(info); + result = fill_spoolss_DriverFileInfo(info, + &info[count], + cservername, + driver->info_3->datafile, + SPOOLSS_DRIVER_FILE_TYPE_DATA, + 0); + W_ERROR_NOT_OK_RETURN(result); + count++; + } + + if (strlen(driver->info_3->helpfile)) { + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + struct spoolss_DriverFileInfo, + count + 1); + W_ERROR_HAVE_NO_MEMORY(info); + result = fill_spoolss_DriverFileInfo(info, + &info[count], + cservername, + driver->info_3->helpfile, + SPOOLSS_DRIVER_FILE_TYPE_HELP, + 0); + W_ERROR_NOT_OK_RETURN(result); + count++; + } + + for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) { + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + struct spoolss_DriverFileInfo, + count + 1); + W_ERROR_HAVE_NO_MEMORY(info); + result = fill_spoolss_DriverFileInfo(info, + &info[count], + cservername, + driver->info_3->dependentfiles[i], + SPOOLSS_DRIVER_FILE_TYPE_OTHER, + 0); + W_ERROR_NOT_OK_RETURN(result); + count++; + } + + *info_p = info; + *count_p = count; + + return WERR_OK; +} + +/******************************************************************** + * fill a spoolss_DriverInfo101 sttruct + ********************************************************************/ + +static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx, + struct spoolss_DriverInfo101 *r, + const NT_PRINTER_DRIVER_INFO_LEVEL *driver, + const char *servername) +{ + const char *cservername = canon_servername(servername); + WERROR result; + + r->version = driver->info_3->cversion; + + r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name); + W_ERROR_HAVE_NO_MEMORY(r->driver_name); + r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment); + W_ERROR_HAVE_NO_MEMORY(r->architecture); + + result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver, + cservername, + &r->file_info, + &r->file_count); + if (!W_ERROR_IS_OK(result)) { + return result; + } + + r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname); + W_ERROR_HAVE_NO_MEMORY(r->monitor_name); + + r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype); + W_ERROR_HAVE_NO_MEMORY(r->default_datatype); + + r->previous_names = string_array_from_driver_info(mem_ctx, + NULL, + cservername); + r->driver_date = 0; + r->driver_version = 0; + + r->manufacturer_name = talloc_strdup(mem_ctx, ""); + W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name); + r->manufacturer_url = talloc_strdup(mem_ctx, ""); + W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url); + r->hardware_id = talloc_strdup(mem_ctx, ""); + W_ERROR_HAVE_NO_MEMORY(r->hardware_id); + r->provider = talloc_strdup(mem_ctx, ""); + W_ERROR_HAVE_NO_MEMORY(r->provider); + + return WERR_OK; +} + /******************************************************************** * construct_printer_driver_info_1 ********************************************************************/ @@ -5077,6 +5245,69 @@ static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx, return status; } +/******************************************************************** + * construct_printer_info_101 + * fill a printer_info_101 struct + ********************************************************************/ + +static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx, + struct spoolss_DriverInfo101 *r, + int snum, + const char *servername, + const char *architecture, + uint32_t version) +{ + NT_PRINTER_INFO_LEVEL *printer = NULL; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + WERROR result; + + ZERO_STRUCT(driver); + + result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)); + + DEBUG(8,("construct_printer_driver_info_101: status: %s\n", + win_errstr(result))); + + if (!W_ERROR_IS_OK(result)) { + return WERR_INVALID_PRINTER_NAME; + } + + result = get_a_printer_driver(&driver, 3, printer->info_2->drivername, + architecture, version); + + DEBUG(8,("construct_printer_driver_info_101: status: %s\n", + win_errstr(result))); + + if (!W_ERROR_IS_OK(result)) { + /* + * Is this a W2k client ? + */ + + if (version < 3) { + free_a_printer(&printer, 2); + return WERR_UNKNOWN_PRINTER_DRIVER; + } + + /* Yes - try again with a WinNT driver. */ + version = 2; + result = get_a_printer_driver(&driver, 3, printer->info_2->drivername, + architecture, version); + DEBUG(8,("construct_printer_driver_info_6: status: %s\n", + win_errstr(result))); + if (!W_ERROR_IS_OK(result)) { + free_a_printer(&printer, 2); + return WERR_UNKNOWN_PRINTER_DRIVER; + } + } + + result = fill_printer_driver_info101(mem_ctx, r, &driver, servername); + + free_a_printer(&printer, 2); + free_a_printer_driver(driver, 3); + + return result; +} + /**************************************************************** _spoolss_GetPrinterDriver2 ****************************************************************/ @@ -5146,13 +5377,15 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p, r->in.architecture, r->in.client_major_version); break; - default: -#if 0 /* JERRY */ case 101: - /* apparently this call is the equivalent of - EnumPrinterDataEx() for the DsDriver key */ + result = construct_printer_driver_info_101(p->mem_ctx, + &r->out.info->info101, + snum, + servername, + r->in.architecture, + r->in.client_major_version); break; -#endif + default: result = WERR_UNKNOWN_LEVEL; break; } -- cgit From 168eb23252c14234d09f7038b9894edf86e0efe1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 2 Apr 2009 18:47:51 +0200 Subject: s3-lsa: don't SAFE_FREE talloced structs. Guenther --- source3/rpc_server/srv_lsa_nt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 5fdcaf2d4a..0eee4a903b 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1434,14 +1434,14 @@ NTSTATUS _lsa_EnumAccounts(pipes_struct *p, sids = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_SidPtr, num_entries - *r->in.resume_handle); if (!sids) { - SAFE_FREE(sid_list); + talloc_free(sid_list); return NT_STATUS_NO_MEMORY; } for (i = *r->in.resume_handle, j = 0; i < num_entries; i++, j++) { sids[j].sid = sid_dup_talloc(p->mem_ctx, &sid_list[i]); if (!sids[j].sid) { - SAFE_FREE(sid_list); + talloc_free(sid_list); return NT_STATUS_NO_MEMORY; } } -- cgit From 31ab1d6a6487fb442ccd5b2cd093b4a2b7b80291 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 2 Apr 2009 18:48:15 +0200 Subject: s3-lsa: use LSA_ROLE definitions in _lsa_QueryInfoPolicy(). Guenther --- source3/rpc_server/srv_lsa_nt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 0eee4a903b..0ce2b40f65 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -648,14 +648,14 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, * only a BDC is a backup controller * of the domain, it controls. */ - info->role.role = 2; + info->role.role = LSA_ROLE_BACKUP; break; default: /* * any other role is a primary * of the domain, it controls. */ - info->role.role = 3; + info->role.role = LSA_ROLE_PRIMARY; break; } break; -- cgit From 621d40332aad9d99b14c45155308a394c31b98b5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 3 Apr 2009 00:30:13 +0200 Subject: s3-build: fix the build after tsocket changes. Metze, please check. Guenther --- source3/Makefile.in | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 9a97d8de64..1578abf6b6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -466,8 +466,6 @@ LIBCLI_LDAP_NDR_OBJ = ../libcli/ldap/ldap_ndr.o LIBTSOCKET_OBJ = ../lib/tsocket/tsocket.o \ ../lib/tsocket/tsocket_helpers.o \ ../lib/tsocket/tsocket_bsd.o \ - ../lib/tsocket/tsocket_recvfrom.o \ - ../lib/tsocket/tsocket_sendto.o \ ../lib/tsocket/tsocket_connect.o \ ../lib/tsocket/tsocket_writev.o \ ../lib/tsocket/tsocket_readv.o -- cgit From b63cd72ae44ae9dcc56b8be95b52d6e47ae1c20f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Apr 2009 10:42:43 +0200 Subject: Use procid_str in debug messages for better cluster-debuggability --- source3/locking/brlock.c | 4 ++-- source3/smbd/oplock.c | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'source3') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index aa522ac780..be2948c531 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -41,11 +41,11 @@ static struct db_context *brlock_db; static void print_lock_struct(unsigned int i, struct lock_struct *pls) { - DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ", + DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ", i, (unsigned int)pls->context.smbpid, (unsigned int)pls->context.tid, - (unsigned int)procid_to_pid(&pls->context.pid) )); + procid_str(debug_ctx(), &pls->context.pid) )); DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n", (double)pls->start, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ce00397bbd..d0d228e78c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -375,8 +375,9 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %s: " + "%s/%lu\n", procid_str(debug_ctx(), &src), + file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -464,8 +465,9 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), + msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -571,8 +573,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, pull_file_id_24((char *)data->data, &id); file_id = (unsigned long)IVAL(data->data, 24); - DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", - (int)procid_to_pid(&src), file_id_string_tos(&id), + DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&id), (unsigned int)file_id)); fsp = initial_break_processing(id, file_id); @@ -667,9 +669,9 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id, - (unsigned int)msg.op_mid)); + DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), + msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ schedule_deferred_open_smb_message(msg.op_mid); @@ -696,8 +698,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), + DEBUG(10, ("Got open retry msg from pid %s: %s mid %u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); -- cgit From 7ee4f168d8b18eaeed9cbdbf2db17090b8d35961 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Apr 2009 10:43:13 +0200 Subject: Use cluster-aware procid_is_me instead of comparing pid's --- source3/smbd/oplock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d0d228e78c..6add9f5fc1 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -419,7 +419,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx } /* Need to wait before sending a break message if we sent ourselves this message. */ - if (procid_to_pid(&src) == sys_getpid()) { + if (procid_is_me(&src)) { wait_before_sending_break(); } @@ -520,7 +520,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, } /* Need to wait before sending a break message if we sent ourselves this message. */ - if (procid_to_pid(&src) == sys_getpid()) { + if (procid_is_me(&src)) { wait_before_sending_break(); } -- cgit From df29f49eddbfcd5c6ac9a26d688a1a3f7a087da5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 9 Dec 2008 13:25:59 +0100 Subject: s3-samr: add support for setting password hashes via samr_SetUserInfo level 21. Guenther --- source3/rpc_server/srv_samr_nt.c | 57 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c60d904b18..a4bfe73f1c 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -3667,8 +3667,9 @@ static bool set_user_info_20(struct samr_UserInfo20 *id20, set_user_info_21 ********************************************************************/ -static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, - struct samr_UserInfo21 *id21, +static NTSTATUS set_user_info_21(struct samr_UserInfo21 *id21, + TALLOC_CTX *mem_ctx, + DATA_BLOB *session_key, struct samu *pwd) { NTSTATUS status; @@ -3686,6 +3687,52 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } + if (id21->fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) { + if (id21->nt_password_set) { + DATA_BLOB in, out; + + if ((id21->nt_owf_password.length != 16) || + (id21->nt_owf_password.size != 16)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!session_key->length) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + + in = data_blob_const(id21->nt_owf_password.array, 16); + out = data_blob_talloc_zero(mem_ctx, 16); + + sess_crypt_blob(&out, &in, session_key, false); + + pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED); + pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); + } + } + + if (id21->fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) { + if (id21->lm_password_set) { + DATA_BLOB in, out; + + if ((id21->lm_owf_password.length != 16) || + (id21->lm_owf_password.size != 16)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!session_key->length) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + + in = data_blob_const(id21->lm_owf_password.array, 16); + out = data_blob_talloc_zero(mem_ctx, 16); + + sess_crypt_blob(&out, &in, session_key, false); + + pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED); + pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); + } + } + /* we need to separately check for an account rename first */ if (id21->account_name.string && @@ -4147,8 +4194,10 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, break; case 21: - status = set_user_info_21(p->mem_ctx, - &info->info21, pwd); + status = set_user_info_21(&info->info21, + p->mem_ctx, + &p->server_info->user_session_key, + pwd); break; case 23: -- cgit From ac4c319ed7559b73ed3232251f9dbc659aa53970 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 12 Feb 2009 20:41:49 +0100 Subject: Pass the current debuglevel down to the forked smbd --- source3/rpc_client/rpc_transport_smbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index bde8d04208..efc57eb243 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -309,7 +309,8 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, printf("no memory"); exit(1); } - if (asprintf(&smbd_cmd, "%s -F -S", smbd_cmd) == -1) { + if (asprintf(&smbd_cmd, "%s -F -S -d %d", smbd_cmd, + DEBUGLEVEL) == -1) { printf("no memory"); exit(1); } -- cgit From 6d760a4a9fef0ca98cca56cc634712a215ab978a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 12 Feb 2009 12:11:16 +0100 Subject: Ensure 0-termination for the forked-smbd debug output --- source3/rpc_client/rpc_transport_smbd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index efc57eb243..d8ab96f7b2 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -88,6 +88,7 @@ static void rpc_cli_smbd_stdout_reader(struct event_context *ev, TALLOC_FREE(fde); return; } + buf[nread] = '\0'; if (conn->stdout_callback.fn != NULL) { conn->stdout_callback.fn(buf, nread, -- cgit From 0421fa90ce2f140da95e51216677834896d77213 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 12 Feb 2009 12:12:04 +0100 Subject: Keep the forked-smbd stdout reader around longer --- source3/rpc_client/rpc_transport_smbd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index d8ab96f7b2..eb64a34d97 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -334,7 +334,7 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, goto nomem; } - if (event_add_fd(ev, subreq, state->conn->stdout_fd, EVENT_FD_READ, + if (event_add_fd(ev, state, state->conn->stdout_fd, EVENT_FD_READ, rpc_cli_smbd_stdout_reader, state->conn) == NULL) { goto nomem; } @@ -458,7 +458,7 @@ static struct tevent_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx, goto fail; } - if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ, + if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ, rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { goto fail; } @@ -529,7 +529,7 @@ static struct tevent_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx, goto fail; } - if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ, + if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ, rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { goto fail; } @@ -602,6 +602,11 @@ struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, state->transport_smbd->conn = conn; state->transport->priv = state->transport_smbd; + if (event_add_fd(ev, state, conn->stdout_fd, EVENT_FD_READ, + rpc_cli_smbd_stdout_reader, conn) == NULL) { + goto fail; + } + subreq = rpc_transport_np_init_send(state, ev, conn->cli, abstract_syntax); if (subreq == NULL) { -- cgit From 3b0572bf91a527674459427c761d45361e40d3ec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 28 Mar 2009 19:58:45 +0100 Subject: Fix smbd crash for close_on_completion handle_trans() can talloc_free "conn" if the client requests close_on_completion. "state" is a talloc_child of conn, so it will be gone when we later free state->data et al. --- source3/smbd/ipc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d39aab4f47..2d5713590d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -754,6 +754,8 @@ void reply_trans(struct smb_request *req) return; } + talloc_steal(talloc_tos(), state); + handle_trans(conn, req, state); SAFE_FREE(state->data); @@ -852,6 +854,8 @@ void reply_transs(struct smb_request *req) return; } + talloc_steal(talloc_tos(), state); + handle_trans(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); -- cgit From ba408a2c826c3200bc7d26f9b6faae0444aea11d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 28 Mar 2009 14:57:57 +0100 Subject: Remove async_req dependency from cli_pull_trans --- source3/libsmb/clitrans.c | 48 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 91fb6e6296..ada2d86f76 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -984,8 +984,9 @@ static void cli_trans_ship_rest(struct async_req *req, cli_req->seqnum = state->seqnum; } -static NTSTATUS cli_pull_trans(struct async_req *req, - struct cli_request *cli_req, +static NTSTATUS cli_pull_trans(uint8_t *inbuf, + uint8_t wct, uint16_t *vwv, + uint16_t num_bytes, uint8_t *bytes, uint8_t smb_cmd, bool expect_first_reply, uint8_t *pnum_setup, uint16_t **psetup, uint32_t *ptotal_param, uint32_t *pnum_param, @@ -994,22 +995,6 @@ static NTSTATUS cli_pull_trans(struct async_req *req, uint32_t *pdata_disp, uint8_t **pdata) { uint32_t param_ofs, data_ofs; - uint8_t wct; - uint16_t *vwv; - uint16_t num_bytes; - uint8_t *bytes; - NTSTATUS status; - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); - - /* - * We can receive something like STATUS_MORE_ENTRIES, so don't use - * !NT_STATUS_IS_OK(status) here. - */ - - if (NT_STATUS_IS_ERR(status)) { - return status; - } if (expect_first_reply) { if ((wct != 0) || (num_bytes != 0)) { @@ -1065,15 +1050,15 @@ static NTSTATUS cli_pull_trans(struct async_req *req, * length. Likewise for param_ofs/param_disp. */ - if (trans_oob(smb_len(cli_req->inbuf), param_ofs, *pnum_param) + if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param) || trans_oob(*ptotal_param, *pparam_disp, *pnum_param) - || trans_oob(smb_len(cli_req->inbuf), data_ofs, *pnum_data) + || trans_oob(smb_len(inbuf), data_ofs, *pnum_data) || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } - *pparam = (uint8_t *)cli_req->inbuf + 4 + param_ofs; - *pdata = (uint8_t *)cli_req->inbuf + 4 + data_ofs; + *pparam = (uint8_t *)inbuf + 4 + param_ofs; + *pdata = (uint8_t *)inbuf + 4 + data_ofs; return NT_STATUS_OK; } @@ -1112,6 +1097,10 @@ static void cli_trans_recv_helper(struct async_req *req) req->private_data, struct cli_request); struct cli_trans_state *state = talloc_get_type_abort( cli_req->recv_helper.priv, struct cli_trans_state); + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; uint8_t num_setup = 0; uint16_t *setup = NULL; uint32_t total_param = 0; @@ -1128,8 +1117,21 @@ static void cli_trans_recv_helper(struct async_req *req) sent_all = (state->param_sent == state->num_param) && (state->data_sent == state->num_data); + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + + /* + * We can receive something like STATUS_MORE_ENTRIES, so don't use + * !NT_STATUS_IS_OK(status) here. + */ + + if (NT_STATUS_IS_ERR(status)) { + async_req_nterror(req, status); + return; + } + status = cli_pull_trans( - req, cli_req, state->cmd, !sent_all, &num_setup, &setup, + (uint8_t *)cli_req->inbuf, wct, vwv, num_bytes, bytes, + state->cmd, !sent_all, &num_setup, &setup, &total_param, &num_param, ¶m_disp, ¶m, &total_data, &num_data, &data_disp, &data); -- cgit From e5c7df34f2d461b0f348fc1b40275a97d918ed9e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 17:01:57 +0200 Subject: Remove a silly check This does not increase security, and if later error messages suck, we have to fix those. --- source3/utils/pdbedit.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3') diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index a5bc0c9bd4..328b2cb1f4 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -847,13 +847,6 @@ int main (int argc, char **argv) POPT_TABLEEND }; - /* we shouldn't have silly checks like this */ - if (getuid() != 0) { - d_fprintf(stderr, "You must be root to use pdbedit\n"); - TALLOC_FREE(frame); - return -1; - } - bin = bout = bdef = NULL; load_case_tables(); -- cgit From 15f6d5e805490b35ed390f731944bc4ac4e3327b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 17:13:02 +0200 Subject: Use the server config file for smbpasswd -a user in make test Without this, smbpasswd generated a SID for the netbios name TORTURE_6. This SID somehow ended up in the user's token for quite a number of tests, leading to NT_STATUS_ACCESS_DENIED. I haven't fully understood what is going on here, but with this patch I could not reproduce the ACCESS_DENIED anymore. It might be coincidence and this patch does not fix anything, but for me it does not really hurt either. Metze, please check! Volker --- source3/script/tests/selftest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index a430d01a0e..d49c5b0ca1 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -282,7 +282,7 @@ MAKE_TEST_BINARY="bin/smbpasswd" export MAKE_TEST_BINARY (echo $PASSWORD; echo $PASSWORD) | \ - bin/smbpasswd -c $CONFFILE -L -s -a $USERNAME >/dev/null || exit 1 + bin/smbpasswd -c $SERVERCONFFILE -L -s -a $USERNAME >/dev/null || exit 1 echo "DONE"; -- cgit From 54c2fe65837bb35f1632af112eaccbbd916a6456 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 07:31:30 +0200 Subject: Fix two c++ warnings in vfs_gpfs.c --- source3/modules/vfs_gpfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 3c061ece79..eaa186ce4f 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -341,7 +341,7 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) gacl_len = sizeof(struct gpfs_acl) + (smb_get_naces(smbacl)-1)*sizeof(gpfs_ace_v4_t); - gacl = TALLOC_SIZE(mem_ctx, gacl_len); + gacl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, gacl_len); if (gacl == NULL) { DEBUG(0, ("talloc failed\n")); errno = ENOMEM; @@ -600,7 +600,7 @@ static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl, len = sizeof(struct gpfs_acl) - sizeof(union gpfs_ace_union) + (pacl->count)*sizeof(gpfs_ace_v1_t); - result = SMB_MALLOC(len); + result = (struct gpfs_acl *)SMB_MALLOC(len); if (result == NULL) { errno = ENOMEM; return result; -- cgit From f2e17a4b24efd8448172f52a2562e6a17562008e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 07:31:47 +0200 Subject: Add prototype for smbd_gpfs_get_realfilename_path --- source3/modules/vfs_gpfs.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3') diff --git a/source3/modules/vfs_gpfs.h b/source3/modules/vfs_gpfs.h index 3c499b0850..efca5603aa 100644 --- a/source3/modules/vfs_gpfs.h +++ b/source3/modules/vfs_gpfs.h @@ -29,4 +29,6 @@ bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, int set_gpfs_lease(int fd, int leasetype); int smbd_gpfs_getacl(char *pathname, int flags, void *acl); int smbd_gpfs_putacl(char *pathname, int flags, void *acl); +int smbd_gpfs_get_realfilename_path(char *pathname, char *filenamep, + int *buflen); void init_gpfs(void); -- cgit From a2d5fe4a0501058aa2b20f4571e382fd629e446b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 07:32:03 +0200 Subject: Make some functions static to vfs_gpfs.c --- source3/modules/vfs_gpfs.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3') diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index eaa186ce4f..b304d8bdc2 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -556,9 +556,9 @@ static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type) return result; } -SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle, - const char *path_p, - SMB_ACL_TYPE_T type) +static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) { gpfs_aclType_t gpfs_type; @@ -577,8 +577,8 @@ SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle, return gpfsacl_get_posix_acl(path_p, gpfs_type); } -SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle, - files_struct *fsp) +static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp) { return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS); } @@ -670,10 +670,10 @@ static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl, return result; } -int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle, - const char *name, - SMB_ACL_TYPE_T type, - SMB_ACL_T theacl) +static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) { struct gpfs_acl *gpfs_acl; int result; @@ -689,15 +689,15 @@ int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle, return result; } -int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle, - files_struct *fsp, - SMB_ACL_T theacl) +static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + SMB_ACL_T theacl) { return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name, SMB_ACL_TYPE_ACCESS, theacl); } -int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle, - const char *path) +static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { errno = ENOTSUP; return -1; -- cgit From 9512640155f3f249e4fd5ad076375592cbd65fc6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 15:29:02 +1100 Subject: s3:smbldap Remove smbldap_get_dn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes one more caller to pull_utf8_allocate() Signed-off-by: Günther Deschner --- source3/include/proto.h | 1 - source3/include/smbldap.h | 3 +-- source3/lib/smbldap.c | 30 ++++-------------------------- source3/passdb/pdb_ldap.c | 43 +++++++++++++++---------------------------- source3/passdb/pdb_nds.c | 4 +++- 5 files changed, 23 insertions(+), 58 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 0a2a8de4a9..c46e7a574c 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -746,7 +746,6 @@ void smbldap_free_struct(struct smbldap_state **ldap_state) ; NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, const char *location, struct smbldap_state **smbldap_state); -char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry); bool smbldap_has_control(LDAP *ld, const char *control); bool smbldap_has_extension(LDAP *ld, const char *extension); bool smbldap_has_naming_context(LDAP *ld, const char *naming_context); diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index a2cb8c5eea..353e01aba6 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -141,7 +141,6 @@ void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, char *value, int max_len); -char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry); int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]); @@ -214,7 +213,7 @@ char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, TALLOC_CTX *mem_ctx); void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result); void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod); -const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, +char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, LDAPMessage *entry); diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index e24d35818c..1dfb02035d 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1649,41 +1649,19 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, return NT_STATUS_OK; } -/******************************************************************* - Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX. -********************************************************************/ -char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry) -{ - char *utf8_dn, *unix_dn; - size_t converted_size; - - utf8_dn = ldap_get_dn(ld, entry); - if (!utf8_dn) { - DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); - return NULL; - } - if (!pull_utf8_allocate(&unix_dn, utf8_dn, &converted_size)) { - DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 " - "[%s]\n", utf8_dn)); - return NULL; - } - ldap_memfree(utf8_dn); - return unix_dn; -} - - const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, - LDAPMessage *entry) + char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *entry) { char *utf8_dn, *unix_dn; size_t converted_size; utf8_dn = ldap_get_dn(ld, entry); if (!utf8_dn) { - DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); + DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n")); return NULL; } if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) { - DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 " + DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 " "[%s]\n", utf8_dn)); return NULL; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 77b19e3de9..b706721e77 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -840,27 +840,27 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, /* Make call to Novell eDirectory ldap extension to get clear text password. NOTE: This will only work if we have an SSL connection to eDirectory. */ - user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + user_dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry); if (user_dn != NULL) { - DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn)); + DEBUG(3, ("init_sam_from_ldap: smbldap_talloc_dn(ctx, %s) returned '%s'\n", username, user_dn)); pwd_len = sizeof(clear_text_pw); if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) { nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd); if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) { - SAFE_FREE(user_dn); + TALLOC_FREE(user_dn); return False; } ZERO_STRUCT(smblmpwd); if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) { - SAFE_FREE(user_dn); + TALLOC_FREE(user_dn); return False; } ZERO_STRUCT(smbntpwd); use_samba_attrs = False; } - SAFE_FREE(user_dn); + TALLOC_FREE(user_dn); } else { DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username)); @@ -1908,7 +1908,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { return NT_STATUS_UNSUCCESSFUL; } @@ -1918,7 +1918,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); - SAFE_FREE(dn); + TALLOC_FREE(dn); if (mods != NULL) ldap_mods_free(mods,True); return NT_STATUS_UNSUCCESSFUL; @@ -1928,7 +1928,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc && (mods == NULL)) { DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); - SAFE_FREE(dn); + TALLOC_FREE(dn); return NT_STATUS_OK; } @@ -1938,7 +1938,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc ldap_mods_free(mods,True); } - SAFE_FREE(dn); + TALLOC_FREE(dn); /* * We need to set the backend private data to NULL here. For example @@ -2147,17 +2147,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s /* Check if we need to update an existing entry */ if (num_result == 1) { - char *tmp; - DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); - tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); - if (!tmp) { - goto fn_exit; - } - dn = talloc_asprintf(ctx, "%s", tmp); - SAFE_FREE(tmp); + dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { status = NT_STATUS_NO_MEMORY; goto fn_exit; @@ -2200,17 +2193,11 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s /* Check if we need to update an existing entry */ if (num_result == 1) { - char *tmp; DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); - tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); - if (!tmp) { - goto fn_exit; - } - dn = talloc_asprintf(ctx, "%s", tmp); - SAFE_FREE(tmp); + dn = smbldap_talloc_dn (ctx, ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { status = NT_STATUS_NO_MEMORY; goto fn_exit; @@ -3525,7 +3512,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; @@ -3540,7 +3527,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods, ldap_mods_free(mods, True); ldap_msgfree(result); - SAFE_FREE(dn); + TALLOC_FREE(dn); if (rc == LDAP_TYPE_OR_VALUE_EXISTS) { return NT_STATUS_MEMBER_IN_ALIAS; @@ -6307,14 +6294,14 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) return NT_STATUS_UNSUCCESSFUL; } - dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } ldap_state->domain_dn = smb_xstrdup(dn); - ldap_memfree(dn); + TALLOC_FREE(dn); domain_sid_string = smbldap_talloc_single_attribute( ldap_state->smbldap_state->ldap_struct, diff --git a/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c index 1edd665d54..08665e4617 100644 --- a/source3/passdb/pdb_nds.c +++ b/source3/passdb/pdb_nds.c @@ -788,7 +788,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry); if (!dn) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -811,6 +811,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, rc = smb_ldap_setup_full_conn(&ld, ldap_state->location); if (rc) { + TALLOC_FREE(dn); return NT_STATUS_INVALID_CONNECTION; } @@ -841,6 +842,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, return nt_status; } } + TALLOC_FREE(dn); } return NT_STATUS_OK; -- cgit From 89278b18195484d3ea5d25e8b19871d64d218a05 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 16:31:51 +1100 Subject: s3:printing Convert nt_printer_publish_ads() to use talloc better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In particular, this removes one more user of pull_utf8_allocate() Andrew Bartlett Signed-off-by: Günther Deschner --- source3/printing/nt_printing.c | 44 +++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'source3') diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index a99485d381..a219380177 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3243,7 +3243,12 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, struct GUID guid; WERROR win_rc = WERR_OK; size_t converted_size; - int ret; + + /* build the ads mods */ + ctx = talloc_init("nt_printer_publish_ads"); + if (ctx == NULL) { + return WERR_NOMEM; + } DEBUG(5, ("publishing printer %s\n", printer->info_2->printername)); @@ -3255,24 +3260,28 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); if (!srv_dn_utf8) { + TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } ads_msgfree(ads, res); srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); if (!srv_cn_utf8) { + TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); return WERR_SERVER_UNAVAILABLE; } /* Now convert to CH_UNIX. */ - if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) { + if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) { + TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); ldap_memfree(srv_cn_utf8); return WERR_SERVER_UNAVAILABLE; } - if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) { + if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) { + TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); ldap_memfree(srv_cn_utf8); - SAFE_FREE(srv_dn); + TALLOC_FREE(srv_dn); return WERR_SERVER_UNAVAILABLE; } @@ -3281,41 +3290,26 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); if (!srv_cn_escaped) { - SAFE_FREE(srv_cn_0); - SAFE_FREE(srv_dn); + TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename); if (!sharename_escaped) { SAFE_FREE(srv_cn_escaped); - SAFE_FREE(srv_cn_0); - SAFE_FREE(srv_dn); + TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } - ret = asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); + prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); - SAFE_FREE(srv_dn); - SAFE_FREE(srv_cn_0); SAFE_FREE(srv_cn_escaped); SAFE_FREE(sharename_escaped); - if (ret == -1) { - return WERR_NOMEM; - } - - /* build the ads mods */ - ctx = talloc_init("nt_printer_publish_ads"); - if (ctx == NULL) { - SAFE_FREE(prt_dn); - return WERR_NOMEM; - } - mods = ads_init_mods(ctx); if (mods == NULL) { SAFE_FREE(prt_dn); - talloc_destroy(ctx); + TALLOC_FREE(ctx); return WERR_NOMEM; } @@ -3336,8 +3330,6 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, if (!ADS_ERR_OK(ads_rc)) DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc))); - talloc_destroy(ctx); - /* retreive the guid and store it locally */ if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { ZERO_STRUCT(guid); @@ -3346,8 +3338,8 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, store_printer_guid(printer->info_2, guid); win_rc = mod_a_printer(printer, 2); } + TALLOC_FREE(ctx); - SAFE_FREE(prt_dn); return win_rc; } -- cgit From 20501876735fc4656083747ba8aa0de9da8fb820 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 17:35:03 +1100 Subject: s3:libads Make ads_get_dn() take a talloc context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove ads_memfree(), which was only ever a wrapper around SAFE_FREE, used only to free the DN from ads_get_ds(). This actually makes libgpo more consistant, as it mixed a talloc and a malloc based string on the same element. Andrew Bartlett Signed-off-by: Günther Deschner --- source3/include/ads_protos.h | 2 +- source3/libads/ldap.c | 69 +++++++++++--------------- source3/libgpo/gpo_ldap.c | 6 +-- source3/libnet/libnet_join.c | 4 +- source3/printing/nt_printing.c | 4 +- source3/utils/net_ads.c | 16 +++--- source3/utils/net_ads_gpo.c | 6 +-- source3/winbindd/idmap_adex/gc_util.c | 8 +-- source3/winbindd/idmap_adex/likewise_cell.c | 4 +- source3/winbindd/idmap_adex/provider_unified.c | 6 +-- source3/winbindd/winbindd_ads.c | 4 +- 11 files changed, 58 insertions(+), 71 deletions(-) (limited to 'source3') diff --git a/source3/include/ads_protos.h b/source3/include/ads_protos.h index a372010b79..502eaa82d9 100644 --- a/source3/include/ads_protos.h +++ b/source3/include/ads_protos.h @@ -3,7 +3,7 @@ */ void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg); -char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg); +char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg); char *ads_get_dn_canonical(ADS_STRUCT *ads, LDAPMessage *msg); char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg, diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index edbd69392c..d274377259 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1266,23 +1266,13 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path, ldap_msgfree(msg); } -/** - * Free up memory from various ads requests - * @param ads connection to ads server - * @param mem Area to free - **/ -void ads_memfree(ADS_STRUCT *ads, void *mem) -{ - SAFE_FREE(mem); -} - /** * Get a dn from search results * @param ads connection to ads server * @param msg Search result * @return dn string **/ - char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg) + char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg) { char *utf8_dn, *unix_dn; size_t converted_size; @@ -1294,7 +1284,7 @@ void ads_memfree(ADS_STRUCT *ads, void *mem) return NULL; } - if (!pull_utf8_allocate(&unix_dn, utf8_dn, &converted_size)) { + if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) { DEBUG(0,("ads_get_dn: string conversion failure utf8 [%s]\n", utf8_dn )); return NULL; @@ -1639,7 +1629,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid) } /* substitute the bind-path from the well-known-guid-search result */ - wkn_dn = ads_get_dn(ads, res); + wkn_dn = ads_get_dn(ads, NULL, res); if (!wkn_dn) { goto out; } @@ -1685,7 +1675,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid) out: SAFE_FREE(base); ads_msgfree(ads, res); - ads_memfree(ads, wkn_dn); + TALLOC_FREE(wkn_dn); if (wkn_dn_exp) { ldap_value_free(wkn_dn_exp); } @@ -1741,14 +1731,14 @@ uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name) return kvno; } - dn_string = ads_get_dn(ads, res); + dn_string = ads_get_dn(ads, NULL, res); if (!dn_string) { DEBUG(0,("ads_get_kvno: out of memory.\n")); ads_msgfree(ads, res); return kvno; } DEBUG(5,("ads_get_kvno: Using: %s\n", dn_string)); - ads_memfree(ads, dn_string); + TALLOC_FREE(dn_string); /* --------------------------------------------------------- * 0 is returned as a default KVNO from this point on... @@ -1836,14 +1826,14 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin talloc_destroy(ctx); return ret; } - dn_string = ads_get_dn(ads, res); + dn_string = ads_get_dn(ads, NULL, res); if (!dn_string) { talloc_destroy(ctx); ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); } ret = ads_gen_mod(ads, dn_string, mods); - ads_memfree(ads,dn_string); + TALLOC_FREE(dn_string); if (!ADS_ERR_OK(ret)) { DEBUG(1,("ads_clear_service_principal_names: Error: Updating Service Principals for machine %s in LDAP\n", machine_name)); @@ -1933,13 +1923,12 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n goto out; } - if ( (dn_string = ads_get_dn(ads, res)) == NULL ) { + if ( (dn_string = ads_get_dn(ads, ctx, res)) == NULL ) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto out; } ret = ads_gen_mod(ads, dn_string, mods); - ads_memfree(ads,dn_string); if (!ADS_ERR_OK(ret)) { DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n")); goto out; @@ -2052,7 +2041,7 @@ ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name, goto done; } - computer_dn = ads_get_dn(ads, res); + computer_dn = ads_get_dn(ads, NULL, res); if (!computer_dn) { rc = ADS_ERROR(LDAP_NO_MEMORY); goto done; @@ -3029,7 +3018,7 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c return ADS_ERROR(LDAP_NO_SUCH_OBJECT); } - dn = ads_get_dn(ads, res); + dn = ads_get_dn(ads, mem_ctx, res); if (dn == NULL) { ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); @@ -3039,18 +3028,18 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn))); if (parent == NULL) { ads_msgfree(ads, res); - ads_memfree(ads, dn); + TALLOC_FREE(dn); return ADS_ERROR(LDAP_NO_MEMORY); } *site_dn = talloc_strdup(mem_ctx, parent); if (*site_dn == NULL) { ads_msgfree(ads, res); - ads_memfree(ads, dn); + TALLOC_FREE(dn); return ADS_ERROR(LDAP_NO_MEMORY); } - ads_memfree(ads, dn); + TALLOC_FREE(dn); ads_msgfree(ads, res); return status; @@ -3140,7 +3129,7 @@ ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads, char *dn = NULL; - dn = ads_get_dn(ads, msg); + dn = ads_get_dn(ads, NULL, msg); if (!dn) { ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); @@ -3149,12 +3138,12 @@ ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads, if (!add_string_to_array(mem_ctx, dn, (const char ***)ous, (int *)num_ous)) { - ads_memfree(ads, dn); + TALLOC_FREE(dn); ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); } - ads_memfree(ads, dn); + TALLOC_FREE(dn); } ads_msgfree(ads, res); @@ -3494,7 +3483,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) return ADS_ERROR_SYSTEM(ENOENT); } - hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg); + hostnameDN = ads_get_dn(ads, NULL, (LDAPMessage *)msg); rc = ldap_delete_ext_s(ads->ldap.ld, hostnameDN, pldap_control, NULL); if (rc) { @@ -3516,7 +3505,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) if (!ADS_ERR_OK(status)) { SAFE_FREE(host); - ads_memfree(ads, hostnameDN); + TALLOC_FREE(hostnameDN); return status; } @@ -3525,9 +3514,9 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) char *dn = NULL; - if ((dn = ads_get_dn(ads, msg_sub)) == NULL) { + if ((dn = ads_get_dn(ads, NULL, msg_sub)) == NULL) { SAFE_FREE(host); - ads_memfree(ads, hostnameDN); + TALLOC_FREE(hostnameDN); return ADS_ERROR(LDAP_NO_MEMORY); } @@ -3535,12 +3524,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) if (!ADS_ERR_OK(status)) { DEBUG(3,("failed to delete dn %s: %s\n", dn, ads_errstr(status))); SAFE_FREE(host); - ads_memfree(ads, dn); - ads_memfree(ads, hostnameDN); + TALLOC_FREE(dn); + TALLOC_FREE(hostnameDN); return status; } - ads_memfree(ads, dn); + TALLOC_FREE(dn); } /* there should be no subordinate objects anymore */ @@ -3550,7 +3539,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) if (!ADS_ERR_OK(status) || ( (ads_count_replies(ads, res)) > 0 ) ) { SAFE_FREE(host); - ads_memfree(ads, hostnameDN); + TALLOC_FREE(hostnameDN); return status; } @@ -3559,12 +3548,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) if (!ADS_ERR_OK(status)) { SAFE_FREE(host); DEBUG(3,("failed to delete dn %s: %s\n", hostnameDN, ads_errstr(status))); - ads_memfree(ads, hostnameDN); + TALLOC_FREE(hostnameDN); return status; } } - ads_memfree(ads, hostnameDN); + TALLOC_FREE(hostnameDN); status = ads_find_machine_acct(ads, &res, host); if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { @@ -3723,7 +3712,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads, goto out; } - dn = ads_get_dn(ads, res); + dn = ads_get_dn(ads, NULL, res); if (dn == NULL) { status = ADS_ERROR(LDAP_NO_MEMORY); goto out; @@ -3746,7 +3735,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads, } } out: - ads_memfree(ads, dn); + TALLOC_FREE(dn); ads_msgfree(ads, res); return status; diff --git a/source3/libgpo/gpo_ldap.c b/source3/libgpo/gpo_ldap.c index 26813864e5..882804b09a 100644 --- a/source3/libgpo/gpo_ldap.c +++ b/source3/libgpo/gpo_ldap.c @@ -415,7 +415,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads, if (gpo_dn) { gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn); } else { - gpo->ds_path = ads_get_dn(ads, res); + gpo->ds_path = ads_get_dn(ads, mem_ctx, res); } ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path); @@ -523,7 +523,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads, return ADS_ERROR(LDAP_NO_SUCH_OBJECT); } - dn = ads_get_dn(ads, res); + dn = ads_get_dn(ads, mem_ctx, res); if (dn == NULL) { ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); @@ -531,7 +531,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads, status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo); ads_msgfree(ads, res); - ads_memfree(ads, dn); + TALLOC_FREE(dn); return status; } diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index ccfd943a8d..fe9fd66fdc 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -303,7 +303,7 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx, goto done; } - dn = ads_get_dn(r->in.ads, res); + dn = ads_get_dn(r->in.ads, mem_ctx, res); if (!dn) { status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); goto done; @@ -317,7 +317,7 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx, done: ads_msgfree(r->in.ads, res); - ads_memfree(r->in.ads, dn); + TALLOC_FREE(dn); return status; } diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index a219380177..40d7cd6347 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3357,13 +3357,13 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, printer->info_2->sharename, global_myname()); if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { - prt_dn = ads_get_dn(ads, res); + prt_dn = ads_get_dn(ads, NULL, res); if (!prt_dn) { ads_msgfree(ads, res); return WERR_NOMEM; } ads_rc = ads_del_dn(ads, prt_dn); - ads_memfree(ads, prt_dn); + TALLOC_FREE(prt_dn); } if (res) { diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 2a66619438..8ff0cdfcf4 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -503,9 +503,9 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv) ads_msgfree(ads, res); status=ads_find_user_acct(ads, &res, argv[0]); if (ADS_ERR_OK(status)) { - userdn = ads_get_dn(ads, res); + userdn = ads_get_dn(ads, NULL, res); ads_del_dn(ads, userdn); - ads_memfree(ads, userdn); + TALLOC_FREE(userdn); } done: @@ -598,10 +598,10 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv) ads_destroy(&ads); return -1; } - userdn = ads_get_dn(ads, res); + userdn = ads_get_dn(ads, NULL, res); ads_msgfree(ads, res); rc = ads_del_dn(ads, userdn); - ads_memfree(ads, userdn); + TALLOC_FREE(userdn); if (ADS_ERR_OK(rc)) { d_printf("User %s deleted\n", argv[0]); ads_destroy(&ads); @@ -757,10 +757,10 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv) ads_destroy(&ads); return -1; } - groupdn = ads_get_dn(ads, res); + groupdn = ads_get_dn(ads, NULL, res); ads_msgfree(ads, res); rc = ads_del_dn(ads, groupdn); - ads_memfree(ads, groupdn); + TALLOC_FREE(groupdn); if (ADS_ERR_OK(rc)) { d_printf("Group %s deleted\n", argv[0]); ads_destroy(&ads); @@ -1740,10 +1740,10 @@ static int net_ads_printer_remove(struct net_context *c, int argc, const char ** return -1; } - prt_dn = ads_get_dn(ads, res); + prt_dn = ads_get_dn(ads, NULL, res); ads_msgfree(ads, res); rc = ads_del_dn(ads, prt_dn); - ads_memfree(ads, prt_dn); + TALLOC_FREE(prt_dn); if (!ADS_ERR_OK(rc)) { d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc)); diff --git a/source3/utils/net_ads_gpo.c b/source3/utils/net_ads_gpo.c index 181cba221d..910c78d05a 100644 --- a/source3/utils/net_ads_gpo.c +++ b/source3/utils/net_ads_gpo.c @@ -257,7 +257,7 @@ static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **ar msg; msg = ads_next_entry(ads, msg)) { - if ((dn = ads_get_dn(ads, msg)) == NULL) { + if ((dn = ads_get_dn(ads, mem_ctx, msg)) == NULL) { goto out; } @@ -266,18 +266,16 @@ static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **ar if (!ADS_ERR_OK(status)) { d_printf("ads_parse_gpo failed: %s\n", ads_errstr(status)); - ads_memfree(ads, dn); goto out; } dump_gpo(ads, mem_ctx, &gpo, 0); - ads_memfree(ads, dn); } out: ads_msgfree(ads, res); - talloc_destroy(mem_ctx); + TALLOC_FREE(mem_ctx); ads_destroy(&ads); return 0; diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c index 6dc02336d5..58e641b630 100644 --- a/source3/winbindd/idmap_adex/gc_util.c +++ b/source3/winbindd/idmap_adex/gc_util.c @@ -592,11 +592,11 @@ done: while (e) { struct winbindd_tdc_domain *domain_rec; - dn = ads_get_dn(ads, e); + dn = ads_get_dn(ads, frame, e); BAIL_ON_PTR_ERROR(dn, nt_status); dns_domain = cell_dn_to_dns(dn); - SAFE_FREE(dn); + TALLOC_FREE(dn); BAIL_ON_PTR_ERROR(dns_domain, nt_status); domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); @@ -666,13 +666,13 @@ static NTSTATUS get_object_account_name(ADS_STRUCT *ads, /* get the name and domain */ - dn = ads_get_dn(ads, msg); + dn = ads_get_dn(ads, frame, msg); BAIL_ON_PTR_ERROR(dn, nt_status); DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn)); dns_domain = cell_dn_to_dns(dn); - SAFE_FREE(dn); + TALLOC_FREE(dn); BAIL_ON_PTR_ERROR(dns_domain, nt_status); domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c index 7723b3e015..7354a367b8 100644 --- a/source3/winbindd/idmap_adex/likewise_cell.c +++ b/source3/winbindd/idmap_adex/likewise_cell.c @@ -400,10 +400,10 @@ done: e!=NULL; e = ads_next_entry(c->conn, e)) { - char *dn = ads_get_dn(c->conn, e); + char *dn = ads_get_dn(c->conn, NULL, e); DEBUGADD(10,(" dn: %s\n", dn ? dn : "")); - SAFE_FREE(dn); + TALLOC_FREE(dn); } } diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c index f18534797e..9134eb4e64 100644 --- a/source3/winbindd/idmap_adex/provider_unified.c +++ b/source3/winbindd/idmap_adex/provider_unified.c @@ -368,7 +368,7 @@ static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list, LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]); while (e) { - entry_dn = ads_get_dn(ads_list[i], e); + entry_dn = ads_get_dn(ads_list[i], NULL, e); BAIL_ON_PTR_ERROR(entry_dn, nt_status); if (check_forest_scope(entry_dn)) { @@ -389,7 +389,7 @@ static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list, } e = ads_next_entry(ads_list[i], e); - SAFE_FREE(entry_dn); + TALLOC_FREE(entry_dn); } } @@ -439,7 +439,7 @@ done: } talloc_destroy(frame); - SAFE_FREE(entry_dn); + TALLOC_FREE(entry_dn); return nt_status; } diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index a76faa7a25..dcf5623d29 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -865,7 +865,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, goto done; } - user_dn = ads_get_dn(ads, msg); + user_dn = ads_get_dn(ads, mem_ctx, msg); if (user_dn == NULL) { status = NT_STATUS_NO_MEMORY; goto done; @@ -942,7 +942,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n", sid_string_dbg(sid))); done: - ads_memfree(ads, user_dn); + TALLOC_FREE(user_dn); ads_msgfree(ads, msg); return status; } -- cgit From ad29104d3df85faa946f10c0d8626cfc993010e5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 19:58:20 +0200 Subject: Add read_smb_send/recv, dumping keepalives --- source3/include/proto.h | 5 +++ source3/lib/util_sock.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index c46e7a574c..0e6dcc7447 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1420,6 +1420,11 @@ int create_pipe_sock(const char *socket_dir, mode_t dir_perms); const char *get_mydnsfullname(void); bool is_myname_or_ipaddr(const char *s); +struct tevent_req *read_smb_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd); +ssize_t read_smb_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + uint8_t **pbuf, int *perrno); /* The following definitions come from lib/util_str.c */ diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index a0dbca1a00..21dd624b54 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1965,3 +1965,90 @@ bool is_myname_or_ipaddr(const char *s) /* No match */ return false; } + +/* + * Read an smb packet asynchronously, discard keepalives + */ + +struct read_smb_state { + struct tevent_context *ev; + int fd; + uint8_t *buf; +}; + +static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data); +static void read_smb_done(struct tevent_req *subreq); + +struct tevent_req *read_smb_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd) +{ + struct tevent_req *result, *subreq; + struct read_smb_state *state; + + result = tevent_req_create(mem_ctx, &state, struct read_smb_state); + if (result == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + + subreq = read_packet_send(state, ev, fd, 4, read_smb_more, NULL); + if (subreq == NULL) { + goto fail; + } + tevent_req_set_callback(subreq, read_smb_done, result); + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data) +{ + if (buflen > 4) { + return 0; /* We've been here, we're done */ + } + return smb_len_large(buf); +} + +static void read_smb_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct read_smb_state *state = tevent_req_data( + req, struct read_smb_state); + ssize_t len; + int err; + + len = read_packet_recv(subreq, state, &state->buf, &err); + TALLOC_FREE(subreq); + if (len == -1) { + tevent_req_error(req, err); + return; + } + + if (CVAL(state->buf, 0) == SMBkeepalive) { + subreq = read_packet_send(state, state->ev, state->fd, 4, + read_smb_more, NULL); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, read_smb_done, req); + return; + } + tevent_req_done(req); +} + +ssize_t read_smb_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + uint8_t **pbuf, int *perrno) +{ + struct read_smb_state *state = tevent_req_data( + req, struct read_smb_state); + + if (tevent_req_is_unix_error(req, perrno)) { + return -1; + } + *pbuf = talloc_move(mem_ctx, &state->buf); + return talloc_get_size(*pbuf); +} -- cgit From 8bdac3615a255f65665939bda070c1b4ba93b908 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 20:18:45 +0200 Subject: Add new async libsmb infrastructure I know this is just yet another iteration, but I like this one much better than the one that exists right now :-) It will do trans and echo requests without a _recv helper and without unnecessary memcpy(). --- source3/include/async_smb.h | 27 ++ source3/include/client.h | 3 + source3/libsmb/async_smb.c | 765 ++++++++++++++++++++++++++++++++++++++++++++ source3/libsmb/clientgen.c | 12 + 4 files changed, 807 insertions(+) (limited to 'source3') diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h index 2ac1101a1e..adbfc6e5ca 100644 --- a/source3/include/async_smb.h +++ b/source3/include/async_smb.h @@ -151,4 +151,31 @@ NTSTATUS cli_pull_error(char *buf); void cli_set_error(struct cli_state *cli, NTSTATUS status); +struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t smb_command, + uint8_t additional_flags, + uint8_t wct, uint16_t *vwv, + int iov_count, + struct iovec *bytes_iov); +bool cli_smb_req_send(struct tevent_req *req); +size_t cli_smb_wct_ofs(struct tevent_req **reqs, int num_reqs); +bool cli_smb_chain_send(struct tevent_req **reqs, int num_reqs); +uint8_t *cli_smb_inbuf(struct tevent_req *req); +bool cli_has_async_calls(struct cli_state *cli); +void cli_smb_req_unset_pending(struct tevent_req *req); +bool cli_smb_req_set_pending(struct tevent_req *req); +uint16_t cli_smb_req_mid(struct tevent_req *req); +void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid); +struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, + uint8_t smb_command, uint8_t additional_flags, + uint8_t wct, uint16_t *vwv, + uint32_t num_bytes, + const uint8_t *bytes); +NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct, + uint8_t *pwct, uint16_t **pvwv, + uint32_t *pnum_bytes, uint8_t **pbytes); + #endif diff --git a/source3/include/client.h b/source3/include/client.h index 73a1d7b554..c10d2109d8 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -291,6 +291,9 @@ struct cli_state { /* Where (if anywhere) this is mounted under DFS. */ char *dfs_mountpoint; + + struct tevent_queue *outgoing; + struct tevent_req **pending; }; typedef struct file_info { diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 86fd5c8bef..4f88cdbd80 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -1133,3 +1133,768 @@ static void cli_state_handler(struct event_context *event_ctx, close(cli->fd); cli->fd = -1; } + +#define MAX_SMB_IOV 5 + +struct cli_smb_state { + struct tevent_context *ev; + struct cli_state *cli; + uint8_t header[smb_wct+1]; /* Space for the header including the wct */ + + /* + * For normal requests, cli_smb_req_send chooses a mid. Secondary + * trans requests need to use the mid of the primary request, so we + * need a place to store it. Assume it's set if != 0. + */ + uint16_t mid; + + uint16_t *vwv; + uint8_t bytecount_buf[2]; + + struct iovec iov[MAX_SMB_IOV+3]; + int iov_count; + + uint8_t *inbuf; + uint32_t seqnum; + int chain_num; + struct tevent_req **chained_requests; +}; + +static uint16_t cli_alloc_mid(struct cli_state *cli) +{ + int num_pending = talloc_array_length(cli->pending); + uint16_t result; + + while (true) { + int i; + + result = cli->mid++; + if (result == 0) { + continue; + } + + for (i=0; ipending[i])) { + break; + } + } + + if (i == num_pending) { + return result; + } + } +} + +void cli_smb_req_unset_pending(struct tevent_req *req) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + struct cli_state *cli = state->cli; + int num_pending = talloc_array_length(cli->pending); + int i; + + if (num_pending == 1) { + /* + * The pending read_smb tevent_req is a child of + * cli->pending. So if nothing is pending anymore, we need to + * delete the socket read fde. + */ + TALLOC_FREE(cli->pending); + return; + } + + for (i=0; ipending[i]) { + break; + } + } + if (i == num_pending) { + /* + * Something's seriously broken. Just returning here is the + * right thing nevertheless, the point of this routine is to + * remove ourselves from cli->pending. + */ + return; + } + + /* + * Remove ourselves from the cli->pending array + */ + if (num_pending > 1) { + cli->pending[i] = cli->pending[num_pending-1]; + } + + /* + * No NULL check here, we're shrinking by sizeof(void *), and + * talloc_realloc just adjusts the size for this. + */ + cli->pending = talloc_realloc(NULL, cli->pending, struct tevent_req *, + num_pending - 1); + return; +} + +static int cli_smb_req_destructor(struct tevent_req *req) +{ + cli_smb_req_unset_pending(req); + return 0; +} + +static void cli_smb_received(struct tevent_req *subreq); + +bool cli_smb_req_set_pending(struct tevent_req *req) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + struct cli_state *cli; + struct tevent_req **pending; + int num_pending; + struct tevent_req *subreq; + + cli = state->cli; + num_pending = talloc_array_length(cli->pending); + + pending = talloc_realloc(cli, cli->pending, struct tevent_req *, + num_pending+1); + if (pending == NULL) { + return false; + } + pending[num_pending] = req; + cli->pending = pending; + talloc_set_destructor(req, cli_smb_req_destructor); + + if (num_pending > 0) { + return true; + } + + /* + * We're the first ones, add the read_smb request that waits for the + * answer from the server + */ + subreq = read_smb_send(cli->pending, state->ev, cli->fd); + if (subreq == NULL) { + cli_smb_req_unset_pending(req); + return false; + } + tevent_req_set_callback(subreq, cli_smb_received, cli); + return true; +} + +/* + * Fetch a smb request's mid. Only valid after the request has been sent by + * cli_smb_req_send(). + */ +uint16_t cli_smb_req_mid(struct tevent_req *req) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + return SVAL(state->header, smb_mid); +} + +void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + state->mid = mid; +} + +static size_t iov_len(const struct iovec *iov, int count) +{ + size_t result = 0; + int i; + for (i=0; i MAX_SMB_IOV) { + /* + * Should not happen :-) + */ + return NULL; + } + + result = tevent_req_create(mem_ctx, &state, struct cli_smb_state); + if (result == NULL) { + return NULL; + } + state->ev = ev; + state->cli = cli; + state->mid = 0; /* Set to auto-choose in cli_smb_req_send */ + state->chain_num = 0; + state->chained_requests = NULL; + + cli_setup_packet_buf(cli, (char *)state->header); + SCVAL(state->header, smb_com, smb_command); + SSVAL(state->header, smb_tid, cli->cnum); + SCVAL(state->header, smb_wct, wct); + + state->vwv = vwv; + + SSVAL(state->bytecount_buf, 0, iov_len(bytes_iov, iov_count)); + + state->iov[0].iov_base = state->header; + state->iov[0].iov_len = sizeof(state->header); + state->iov[1].iov_base = state->vwv; + state->iov[1].iov_len = wct * sizeof(uint16_t); + state->iov[2].iov_base = state->bytecount_buf; + state->iov[2].iov_len = sizeof(uint16_t); + + if (iov_count != 0) { + memcpy(&state->iov[3], bytes_iov, + iov_count * sizeof(*bytes_iov)); + } + state->iov_count = iov_count + 3; + + return result; +} + +static bool cli_signv(struct cli_state *cli, struct iovec *iov, int count, + uint32_t *seqnum) +{ + uint8_t *buf; + + /* + * Obvious optimization: Make cli_calculate_sign_mac work with struct + * iovec directly. MD5Update would do that just fine. + */ + + if ((count <= 0) || (iov[0].iov_len < smb_wct)) { + return false; + } + + buf = iov_concat(talloc_tos(), iov, count); + if (buf == NULL) { + return false; + } + + cli_calculate_sign_mac(cli, (char *)buf, seqnum); + memcpy(iov[0].iov_base, buf, iov[0].iov_len); + + TALLOC_FREE(buf); + return true; +} + +static void cli_smb_sent(struct tevent_req *subreq); + +static bool cli_smb_req_iov_send(struct tevent_req *req, + struct cli_smb_state *state, + struct iovec *iov, int iov_count) +{ + struct tevent_req *subreq; + + if (iov[0].iov_len < smb_wct) { + return false; + } + + if (state->mid != 0) { + SSVAL(iov[0].iov_base, smb_mid, state->mid); + } else { + SSVAL(iov[0].iov_base, smb_mid, cli_alloc_mid(state->cli)); + } + + smb_setlen((char *)iov[0].iov_base, iov_len(iov, iov_count) - 4); + + if (!cli_signv(state->cli, iov, iov_count, &state->seqnum)) { + return false; + } + + if (cli_encryption_on(state->cli)) { + NTSTATUS status; + char *buf, *enc_buf; + + buf = (char *)iov_concat(talloc_tos(), iov, iov_count); + if (buf == NULL) { + return false; + } + status = cli_encrypt_message(state->cli, (char *)buf, + &enc_buf); + TALLOC_FREE(buf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error in encrypting client message: %s\n", + nt_errstr(status))); + return false; + } + buf = (char *)talloc_memdup(state, enc_buf, + smb_len(enc_buf)+4); + SAFE_FREE(enc_buf); + if (buf == NULL) { + return false; + } + iov[0].iov_base = buf; + iov[0].iov_len = talloc_get_size(buf); + subreq = writev_send(state, state->ev, state->cli->outgoing, + state->cli->fd, iov, 1); + } else { + subreq = writev_send(state, state->ev, state->cli->outgoing, + state->cli->fd, iov, iov_count); + } + if (subreq == NULL) { + return false; + } + tevent_req_set_callback(subreq, cli_smb_sent, req); + return true; +} + +bool cli_smb_req_send(struct tevent_req *req) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + + return cli_smb_req_iov_send(req, state, state->iov, state->iov_count); +} + +struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t smb_command, + uint8_t additional_flags, + uint8_t wct, uint16_t *vwv, + uint32_t num_bytes, + const uint8_t *bytes) +{ + struct tevent_req *req; + struct iovec iov; + + iov.iov_base = CONST_DISCARD(char *, bytes); + iov.iov_len = num_bytes; + + req = cli_smb_req_create(mem_ctx, ev, cli, smb_command, + additional_flags, wct, vwv, 1, &iov); + if (req == NULL) { + return NULL; + } + if (!cli_smb_req_send(req)) { + TALLOC_FREE(req); + } + return req; +} + +static void cli_smb_sent(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + ssize_t nwritten; + int err; + + nwritten = writev_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nwritten == -1) { + tevent_req_nterror(req, map_nt_error_from_unix(err)); + return; + } + + switch (CVAL(state->header, smb_com)) { + case SMBtranss: + case SMBtranss2: + case SMBnttranss: + case SMBntcancel: + state->inbuf = NULL; + tevent_req_done(req); + return; + case SMBlockingX: + if ((CVAL(state->header, smb_wct) == 8) && + (CVAL(state->vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) { + state->inbuf = NULL; + tevent_req_done(req); + return; + } + } + + if (!cli_smb_req_set_pending(req)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } +} + +static void cli_smb_received(struct tevent_req *subreq) +{ + struct cli_state *cli = tevent_req_callback_data( + subreq, struct cli_state); + struct tevent_req *req; + struct cli_smb_state *state; + struct tevent_context *ev; + NTSTATUS status; + uint8_t *inbuf; + ssize_t received; + int num_pending; + int i, err; + uint16_t mid; + + received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err); + TALLOC_FREE(subreq); + if (received == -1) { + status = map_nt_error_from_unix(err); + goto fail; + } + + if ((IVAL(inbuf, 4) != 0x424d53ff) /* 0xFF"SMB" */ + && (SVAL(inbuf, 4) != 0x45ff)) /* 0xFF"E" */ { + DEBUG(10, ("Got non-SMB PDU\n")); + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto fail; + } + + if (cli_encryption_on(cli) && (CVAL(inbuf, 0) == 0)) { + uint16_t enc_ctx_num; + + status = get_enc_ctx_num(inbuf, &enc_ctx_num); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("get_enc_ctx_num returned %s\n", + nt_errstr(status))); + goto fail; + } + + if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) { + DEBUG(10, ("wrong enc_ctx %d, expected %d\n", + enc_ctx_num, + cli->trans_enc_state->enc_ctx_num)); + status = NT_STATUS_INVALID_HANDLE; + goto fail; + } + + status = common_decrypt_buffer(cli->trans_enc_state, + (char *)inbuf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("common_decrypt_buffer returned %s\n", + nt_errstr(status))); + goto fail; + } + } + + mid = SVAL(inbuf, smb_mid); + num_pending = talloc_array_length(cli->pending); + + for (i=0; ipending[i])) { + break; + } + } + if (i == num_pending) { + /* Dump unexpected reply */ + TALLOC_FREE(inbuf); + goto done; + } + + req = cli->pending[i]; + state = tevent_req_data(req, struct cli_smb_state); + ev = state->ev; + + if (!cli_check_sign_mac(cli, (char *)inbuf, state->seqnum+1)) { + DEBUG(10, ("cli_check_sign_mac failed\n")); + TALLOC_FREE(inbuf); + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + + if (state->chained_requests == NULL) { + state->inbuf = talloc_move(state, &inbuf); + talloc_set_destructor(req, NULL); + cli_smb_req_destructor(req); + tevent_req_done(req); + } else { + struct tevent_req **chain = talloc_move( + talloc_tos(), &state->chained_requests); + int num_chained = talloc_array_length(chain); + + for (i=0; iinbuf = inbuf; + state->chain_num = i; + tevent_req_done(chain[i]); + } + TALLOC_FREE(inbuf); + TALLOC_FREE(chain); + } + done: + if (talloc_array_length(cli->pending) > 0) { + /* + * Set up another read request for the other pending cli_smb + * requests + */ + state = tevent_req_data(cli->pending[0], struct cli_smb_state); + subreq = read_smb_send(cli->pending, state->ev, cli->fd); + if (subreq == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + tevent_req_set_callback(subreq, cli_smb_received, cli); + } + return; + fail: + /* + * Cancel all pending requests. We don't do a for-loop walking + * cli->pending because that array changes in + * cli_smb_req_destructor(). + */ + while (talloc_array_length(cli->pending) > 0) { + req = cli->pending[0]; + talloc_set_destructor(req, NULL); + cli_smb_req_destructor(req); + tevent_req_nterror(req, status); + } +} + +NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct, + uint8_t *pwct, uint16_t **pvwv, + uint32_t *pnum_bytes, uint8_t **pbytes) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + NTSTATUS status = NT_STATUS_OK; + uint8_t cmd, wct; + uint16_t num_bytes; + size_t wct_ofs, bytes_offset; + int i; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + + if (state->inbuf == NULL) { + /* This was a request without a reply */ + return NT_STATUS_OK; + } + + wct_ofs = smb_wct; + cmd = CVAL(state->inbuf, smb_com); + + for (i=0; ichain_num; i++) { + if (i < state->chain_num-1) { + if (cmd == 0xff) { + return NT_STATUS_REQUEST_ABORTED; + } + if (!is_andx_req(cmd)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + } + + if (!have_andx_command((char *)state->inbuf, wct_ofs)) { + /* + * This request was not completed because a previous + * request in the chain had received an error. + */ + return NT_STATUS_REQUEST_ABORTED; + } + + wct_ofs = SVAL(state->inbuf, wct_ofs + 3); + + /* + * Skip the all-present length field. No overflow, we've just + * put a 16-bit value into a size_t. + */ + wct_ofs += 4; + + if (wct_ofs+2 > talloc_get_size(state->inbuf)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + cmd = CVAL(state->inbuf, wct_ofs + 1); + } + + status = cli_pull_error((char *)state->inbuf); + + if (!have_andx_command((char *)state->inbuf, wct_ofs) + && NT_STATUS_IS_ERR(status)) { + /* + * The last command takes the error code. All further commands + * down the requested chain will get a + * NT_STATUS_REQUEST_ABORTED. + */ + return status; + } + + wct = CVAL(state->inbuf, wct_ofs); + bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t); + num_bytes = SVAL(state->inbuf, bytes_offset); + + if (wct < min_wct) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + /* + * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes + * is a 16-bit value. So bytes_offset being size_t should be far from + * wrapping. + */ + if ((bytes_offset + 2 > talloc_get_size(state->inbuf)) + || (bytes_offset > 0xffff)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + if (pwct != NULL) { + *pwct = wct; + } + if (pvwv != NULL) { + *pvwv = (uint16_t *)(state->inbuf + wct_ofs + 1); + } + if (pnum_bytes != NULL) { + *pnum_bytes = num_bytes; + } + if (pbytes != NULL) { + *pbytes = (uint8_t *)state->inbuf + bytes_offset + 2; + } + + return NT_STATUS_OK; +} + +size_t cli_smb_wct_ofs(struct tevent_req **reqs, int num_reqs) +{ + size_t wct_ofs; + int i; + + wct_ofs = smb_wct - 4; + + for (i=0; iiov+1, state->iov_count-1); + wct_ofs = (wct_ofs + 3) & ~3; + } + return wct_ofs; +} + +bool cli_smb_chain_send(struct tevent_req **reqs, int num_reqs) +{ + struct cli_smb_state *first_state = tevent_req_data( + reqs[0], struct cli_smb_state); + struct cli_smb_state *last_state = tevent_req_data( + reqs[num_reqs-1], struct cli_smb_state); + struct cli_smb_state *state; + size_t wct_offset; + size_t chain_padding = 0; + int i, iovlen; + struct iovec *iov = NULL; + struct iovec *this_iov; + + iovlen = 0; + for (i=0; iiov_count; + } + + iov = talloc_array(last_state, struct iovec, iovlen); + if (iov == NULL) { + goto fail; + } + + first_state->chained_requests = (struct tevent_req **)talloc_memdup( + last_state, reqs, sizeof(*reqs) * num_reqs); + if (first_state->chained_requests == NULL) { + goto fail; + } + + wct_offset = smb_wct - 4; + this_iov = iov; + + for (i=0; iheader, smb_com)) + || CVAL(state->header, smb_wct) < 2) { + goto fail; + } + } + + wct_offset += iov_len(state->iov+1, state->iov_count-1) + 1; + if ((wct_offset % 4) != 0) { + next_padding = 4 - (wct_offset % 4); + } + wct_offset += next_padding; + vwv = state->vwv; + + if (i < num_reqs-1) { + struct cli_smb_state *next_state = tevent_req_data( + reqs[i+1], struct cli_smb_state); + SCVAL(vwv+0, 0, CVAL(next_state->header, smb_com)); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, wct_offset); + } else if (is_andx_req(CVAL(state->header, smb_com))) { + /* properly end the chain */ + SCVAL(vwv+0, 0, 0xff); + SCVAL(vwv+0, 1, 0xff); + SSVAL(vwv+1, 0, 0); + } + + if (i == 0) { + this_iov[0] = state->iov[0]; + } else { + /* + * This one is a bit subtle. We have to add + * chain_padding bytes between the requests, and we + * have to also include the wct field of the + * subsequent requests. We use the subsequent header + * for the padding, it contains the wct field in its + * last byte. + */ + this_iov[0].iov_len = chain_padding+1; + this_iov[0].iov_base = &state->header[ + sizeof(state->header) - this_iov[0].iov_len]; + memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1); + } + memcpy(this_iov+1, state->iov+1, + sizeof(struct iovec) * (state->iov_count-1)); + this_iov += state->iov_count; + chain_padding = next_padding; + } + + if (!cli_smb_req_iov_send(reqs[0], last_state, iov, iovlen)) { + goto fail; + } + return true; + fail: + TALLOC_FREE(iov); + return false; +} + +uint8_t *cli_smb_inbuf(struct tevent_req *req) +{ + struct cli_smb_state *state = tevent_req_data( + req, struct cli_smb_state); + return state->inbuf; +} + +bool cli_has_async_calls(struct cli_state *cli) +{ + return ((tevent_queue_length(cli->outgoing) != 0) + || (talloc_array_length(cli->pending) != 0)); +} diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 6186387076..450a7cf4cd 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -650,6 +650,12 @@ struct cli_state *cli_initialise_ex(int signing_state) goto error; } + cli->outgoing = tevent_queue_create(cli, "cli_outgoing"); + if (cli->outgoing == NULL) { + goto error; + } + cli->pending = NULL; + cli->initialised = 1; return cli; @@ -740,6 +746,12 @@ void cli_shutdown(struct cli_state *cli) cli->fd = -1; cli->smb_rw_error = SMB_READ_OK; + /* + * Need to free pending first, they remove themselves + */ + while (cli->pending) { + talloc_free(cli->pending[0]); + } TALLOC_FREE(cli); } -- cgit From 0a4cdad324291d6c91b569c4fc8362a8383965fe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 23:16:34 +0200 Subject: Remove the CHAIN1 test -- will come back later --- source3/script/tests/test_smbtorture_s3.sh | 2 +- source3/torture/torture.c | 99 ------------------------------ 2 files changed, 1 insertion(+), 100 deletions(-) (limited to 'source3') diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh index 70c6d34c88..842277b357 100755 --- a/source3/script/tests/test_smbtorture_s3.sh +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -27,7 +27,7 @@ tests="$tests UNLINK BROWSE ATTR TRANS2 TORTURE " tests="$tests OPLOCK1 OPLOCK2 OPLOCK3" tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3" tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K" -tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE CHAIN1" +tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE" skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN" skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST" diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 1b9e394a68..c62bdfe0fb 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5023,104 +5023,6 @@ static bool subst_test(const char *str, const char *user, const char *domain, return result; } -static void chain1_open_completion(struct async_req *req) -{ - int fnum; - NTSTATUS status; - - status = cli_open_recv(req, &fnum); - TALLOC_FREE(req); - - d_printf("cli_open_recv returned %s: %d\n", - nt_errstr(status), - NT_STATUS_IS_OK(status) ? fnum : -1); -} - -static void chain1_read_completion(struct async_req *req) -{ - NTSTATUS status; - ssize_t received; - uint8_t *rcvbuf; - - status = cli_read_andx_recv(req, &received, &rcvbuf); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(req); - d_printf("cli_read_andx_recv returned %s\n", - nt_errstr(status)); - return; - } - - d_printf("got %d bytes: %.*s\n", (int)received, (int)received, - (char *)rcvbuf); - TALLOC_FREE(req); -} - -static void chain1_write_completion(struct async_req *req) -{ - NTSTATUS status; - size_t written; - - status = cli_write_andx_recv(req, &written); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(req); - d_printf("cli_write_andx_recv returned %s\n", - nt_errstr(status)); - return; - } - - d_printf("wrote %d bytes\n", (int)written); - TALLOC_FREE(req); -} - -static void chain1_close_completion(struct async_req *req) -{ - NTSTATUS status; - - status = cli_close_recv(req); - *((bool *)(req->async.priv)) = true; - - TALLOC_FREE(req); - - d_printf("cli_close returned %s\n", nt_errstr(status)); -} - -static bool run_chain1(int dummy) -{ - struct cli_state *cli1; - struct event_context *evt = event_context_init(NULL); - struct async_req *reqs[4]; - bool done = false; - const char *text = "hallo"; - - printf("starting chain1 test\n"); - if (!torture_open_connection(&cli1, 0)) { - return False; - } - - cli_sockopt(cli1, sockops); - - cli_chain_cork(cli1, evt, 0); - reqs[0] = cli_open_send(talloc_tos(), evt, cli1, "\\test", - O_CREAT|O_RDWR, 0); - reqs[0]->async.fn = chain1_open_completion; - reqs[1] = cli_write_andx_send(talloc_tos(), evt, cli1, 0, 0, - (uint8_t *)text, 0, strlen(text)); - reqs[1]->async.fn = chain1_write_completion; - reqs[2] = cli_read_andx_send(talloc_tos(), evt, cli1, 0, 1, 10); - reqs[2]->async.fn = chain1_read_completion; - reqs[3] = cli_close_send(talloc_tos(), evt, cli1, 0); - reqs[3]->async.fn = chain1_close_completion; - reqs[3]->async.priv = (void *)&done; - cli_chain_uncork(cli1); - - while (!done) { - event_loop_once(evt); - } - - torture_close_connection(cli1); - return True; -} - static size_t null_source(uint8_t *buf, size_t n, void *priv) { size_t *to_pull = (size_t *)priv; @@ -5828,7 +5730,6 @@ static struct { {"FDSESS", run_fdsesstest, 0}, { "EATEST", run_eatest, 0}, { "SESSSETUP_BENCH", run_sesssetup_bench, 0}, - { "CHAIN1", run_chain1, 0}, { "WINDOWS-WRITE", run_windows_write, 0}, { "CLI_ECHO", run_cli_echo, 0}, { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, -- cgit From dec928e884f492c7a5e5e8c87e2ff0c1944da5f1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 20:48:16 +0200 Subject: Convert cli_echo to tevent_req --- source3/include/proto.h | 8 +-- source3/libsmb/clientgen.c | 145 +++++++++++++++++++++------------------------ source3/torture/torture.c | 15 +---- 3 files changed, 71 insertions(+), 97 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 0e6dcc7447..fc1d4618a3 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2444,10 +2444,10 @@ void cli_sockopt(struct cli_state *cli, const char *options); uint16 cli_setpid(struct cli_state *cli, uint16 pid); bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive); bool cli_send_keepalive(struct cli_state *cli); -struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, uint16_t num_echos, - DATA_BLOB data); -NTSTATUS cli_echo_recv(struct async_req *req); +struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, uint16_t num_echos, + DATA_BLOB data); +NTSTATUS cli_echo_recv(struct tevent_req *req); NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data); bool cli_ucs2(struct cli_state *cli); bool is_andx_req(uint8_t cmd); diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 450a7cf4cd..45addc2163 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -805,90 +805,72 @@ bool cli_send_keepalive(struct cli_state *cli) return true; } -/** - * @brief: Collect a echo reply - * @param[in] req The corresponding async request - * - * There might be more than one echo reply. This helper pulls the reply out of - * the data stream. If all expected replies have arrived, declare the - * async_req done. - */ - -static void cli_echo_recv_helper(struct async_req *req) -{ - struct cli_request *cli_req; - uint8_t wct; - uint16_t *vwv; - uint16_t num_bytes; - uint8_t *bytes; - NTSTATUS status; +struct cli_echo_state { + uint16_t vwv[1]; + DATA_BLOB data; + int num_echos; +}; - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); - if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); - return; - } +static void cli_echo_done(struct tevent_req *subreq); - cli_req = talloc_get_type_abort(req->private_data, struct cli_request); +struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, uint16_t num_echos, + DATA_BLOB data) +{ + struct tevent_req *req, *subreq; + struct cli_echo_state *state; - if ((num_bytes != cli_req->data.echo.data.length) - || (memcmp(cli_req->data.echo.data.data, bytes, - num_bytes) != 0)) { - async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; + req = tevent_req_create(mem_ctx, &state, struct cli_echo_state); + if (req == NULL) { + return NULL; } + SSVAL(state->vwv, 0, num_echos); + state->data = data; + state->num_echos = num_echos; - cli_req->data.echo.num_echos -= 1; - - if (cli_req->data.echo.num_echos == 0) { - async_req_done(req); - return; + subreq = cli_smb_send(state, ev, cli, SMBecho, 0, 1, state->vwv, + data.length, data.data); + if (subreq == NULL) { + goto fail; } - - return; + tevent_req_set_callback(subreq, cli_echo_done, req); + return req; + fail: + TALLOC_FREE(req); + return NULL; } -/** - * @brief Send SMBEcho requests - * @param[in] mem_ctx The memory context to put the async_req on - * @param[in] ev The event context that will call us back - * @param[in] cli The connection to send the echo to - * @param[in] num_echos How many times do we want to get the reply? - * @param[in] data The data we want to get back - * @retval The async request - */ - -struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, uint16_t num_echos, - DATA_BLOB data) +static void cli_echo_done(struct tevent_req *subreq) { - uint16_t vwv[1]; - uint8_t *data_copy; - struct async_req *result; - struct cli_request *req; - - SSVAL(vwv, 0, num_echos); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_echo_state *state = tevent_req_data( + req, struct cli_echo_state); + NTSTATUS status; + uint32_t num_bytes; + uint8_t *bytes; - data_copy = (uint8_t *)talloc_memdup(mem_ctx, data.data, data.length); - if (data_copy == NULL) { - return NULL; + status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } - - result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, 0, - data.length, data.data); - if (result == NULL) { - TALLOC_FREE(data_copy); - return NULL; + if ((num_bytes != state->data.length) + || (memcmp(bytes, state->data.data, num_bytes) != 0)) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } - req = talloc_get_type_abort(result->private_data, struct cli_request); - - req->data.echo.num_echos = num_echos; - req->data.echo.data.data = talloc_move(req, &data_copy); - req->data.echo.data.length = data.length; - req->recv_helper.fn = cli_echo_recv_helper; + state->num_echos -=1; + if (state->num_echos == 0) { + tevent_req_done(req); + return; + } - return result; + if (!cli_smb_req_set_pending(subreq)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } } /** @@ -897,9 +879,9 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, * @retval Did the server reply correctly? */ -NTSTATUS cli_echo_recv(struct async_req *req) +NTSTATUS cli_echo_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } /** @@ -916,35 +898,40 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data) { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + status = NT_STATUS_INVALID_PARAMETER; goto fail; } ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = cli_echo_send(frame, ev, cli, num_echos, data); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_echo_recv(req); - fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index c62bdfe0fb..a4c1721fe6 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5101,8 +5101,6 @@ static bool run_windows_write(int dummy) static bool run_cli_echo(int dummy) { struct cli_state *cli; - struct event_context *ev = event_context_init(NULL); - struct async_req *req; NTSTATUS status; printf("starting cli_echo test\n"); @@ -5111,21 +5109,10 @@ static bool run_cli_echo(int dummy) } cli_sockopt(cli, sockops); - req = cli_echo_send(ev, ev, cli, 5, data_blob_const("hello", 5)); - if (req == NULL) { - d_printf("cli_echo_send failed\n"); - return false; - } + status = cli_echo(cli, 5, data_blob_const("hello", 5)); - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); - } - - status = cli_echo_recv(req); d_printf("cli_echo returned %s\n", nt_errstr(status)); - TALLOC_FREE(req); - torture_close_connection(cli); return NT_STATUS_IS_OK(status); } -- cgit From 7ef78bd7b5b5d1b2c5c06d1170f80ea77f036353 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 20:51:52 +0200 Subject: Convert cli_trans to tevent_req --- source3/include/proto.h | 6 +- source3/libsmb/clitrans.c | 654 ++++++++++++++-------------------- source3/rpc_client/rpc_transport_np.c | 14 +- 3 files changed, 281 insertions(+), 393 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index fc1d4618a3..b07cecc136 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2889,14 +2889,14 @@ bool cli_send_nt_trans(struct cli_state *cli, bool cli_receive_nt_trans(struct cli_state *cli, char **param, unsigned int *param_len, char **data, unsigned int *data_len); -struct async_req *cli_trans_send( +struct tevent_req *cli_trans_send( TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, uint8_t trans_cmd, + struct cli_state *cli, uint8_t cmd, const char *pipe_name, uint16_t fid, uint16_t function, int flags, uint16_t *setup, uint8_t num_setup, uint8_t max_setup, uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data); -NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint16_t **setup, uint8_t *num_setup, uint8_t **param, uint32_t *num_param, uint8_t **data, uint32_t *num_data); diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index ada2d86f76..3a6aa9e72c 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -704,6 +704,8 @@ struct cli_trans_state { uint16_t mid; uint32_t seqnum; const char *pipe_name; + uint8_t *pipe_name_conv; + size_t pipe_name_conv_len; uint16_t fid; uint16_t function; int flags; @@ -720,27 +722,131 @@ struct cli_trans_state { struct trans_recvblob rdata; TALLOC_CTX *secondary_request_ctx; + + struct iovec iov[4]; + uint8_t pad[4]; + uint16_t vwv[32]; }; -static void cli_trans_recv_helper(struct async_req *req); +static NTSTATUS cli_pull_trans(uint8_t *inbuf, + uint8_t wct, uint16_t *vwv, + uint16_t num_bytes, uint8_t *bytes, + uint8_t smb_cmd, bool expect_first_reply, + uint8_t *pnum_setup, uint16_t **psetup, + uint32_t *ptotal_param, uint32_t *pnum_param, + uint32_t *pparam_disp, uint8_t **pparam, + uint32_t *ptotal_data, uint32_t *pnum_data, + uint32_t *pdata_disp, uint8_t **pdata) +{ + uint32_t param_ofs, data_ofs; + + if (expect_first_reply) { + if ((wct != 0) || (num_bytes != 0)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + return NT_STATUS_OK; + } + + switch (smb_cmd) { + case SMBtrans: + case SMBtrans2: + if (wct < 10) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + *ptotal_param = SVAL(vwv + 0, 0); + *ptotal_data = SVAL(vwv + 1, 0); + *pnum_param = SVAL(vwv + 3, 0); + param_ofs = SVAL(vwv + 4, 0); + *pparam_disp = SVAL(vwv + 5, 0); + *pnum_data = SVAL(vwv + 6, 0); + data_ofs = SVAL(vwv + 7, 0); + *pdata_disp = SVAL(vwv + 8, 0); + *pnum_setup = CVAL(vwv + 9, 0); + if (wct < 10 + (*pnum_setup)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + *psetup = vwv + 10; -static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, - struct cli_trans_state *state) + break; + case SMBnttrans: + if (wct < 18) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + *ptotal_param = IVAL(vwv, 3); + *ptotal_data = IVAL(vwv, 7); + *pnum_param = IVAL(vwv, 11); + param_ofs = IVAL(vwv, 15); + *pparam_disp = IVAL(vwv, 19); + *pnum_data = IVAL(vwv, 23); + data_ofs = IVAL(vwv, 27); + *pdata_disp = IVAL(vwv, 31); + *pnum_setup = CVAL(vwv, 35); + *psetup = vwv + 18; + break; + + default: + return NT_STATUS_INTERNAL_ERROR; + } + + /* + * Check for buffer overflows. data_ofs needs to be checked against + * the incoming buffer length, data_disp against the total + * length. Likewise for param_ofs/param_disp. + */ + + if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param) + || trans_oob(*ptotal_param, *pparam_disp, *pnum_param) + || trans_oob(smb_len(inbuf), data_ofs, *pnum_data) + || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pparam = (uint8_t *)inbuf + 4 + param_ofs; + *pdata = (uint8_t *)inbuf + 4 + data_ofs; + + return NT_STATUS_OK; +} + +static NTSTATUS cli_trans_pull_blob(TALLOC_CTX *mem_ctx, + struct trans_recvblob *blob, + uint32_t total, uint32_t thistime, + uint8_t *buf, uint32_t displacement) { - TALLOC_CTX *frame; - struct async_req *result = NULL; - struct cli_request *cli_req; - uint8_t wct; - uint16_t *vwv; - uint8_t *bytes = NULL; + if (blob->data == NULL) { + if (total > blob->max) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + blob->total = total; + blob->data = TALLOC_ARRAY(mem_ctx, uint8_t, total); + if (blob->data == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + if (total > blob->total) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + if (thistime) { + memcpy(blob->data + displacement, buf, thistime); + blob->received += thistime; + } + + return NT_STATUS_OK; +} + +static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct, + int *piov_count) +{ + uint8_t wct = 0; + struct iovec *iov = state->iov; + uint8_t *pad = state->pad; + uint16_t *vwv = state->vwv; uint16_t param_offset; uint16_t this_param = 0; uint16_t this_data = 0; uint32_t useable_space; uint8_t cmd; - uint8_t pad[3]; - - frame = talloc_stackframe(); cmd = state->cmd; @@ -751,39 +857,26 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, param_offset = smb_size - 4; - bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 0); /* padding */ - if (bytes == NULL) { - goto fail; - } - switch (cmd) { case SMBtrans: pad[0] = 0; - bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes, - data_blob_const(pad, 1)); - if (bytes == NULL) { - goto fail; - } - bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), - state->pipe_name, - strlen(state->pipe_name)+1, NULL); - if (bytes == NULL) { - goto fail; - } + iov[0].iov_base = pad; + iov[0].iov_len = 1; + iov[1].iov_base = state->pipe_name_conv; + iov[1].iov_len = state->pipe_name_conv_len; wct = 14 + state->num_setup; - param_offset += talloc_get_size(bytes); + param_offset += iov[0].iov_len + iov[1].iov_len; + iov += 2; break; case SMBtrans2: pad[0] = 0; pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */ pad[2] = ' '; - bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes, - data_blob_const(pad, 3)); - if (bytes == NULL) { - goto fail; - } + iov[0].iov_base = pad; + iov[0].iov_len = 3; wct = 14 + state->num_setup; - param_offset += talloc_get_size(bytes); + param_offset += 3; + iov += 1; break; case SMBtranss: wct = 8; @@ -797,8 +890,6 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, case SMBnttranss: wct = 18; break; - default: - goto fail; } useable_space = state->cli->max_xmit - smb_size - sizeof(uint16_t)*wct; @@ -806,17 +897,19 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, if (state->param_sent < state->num_param) { this_param = MIN(state->num_param - state->param_sent, useable_space); + iov[0].iov_base = state->param + state->param_sent; + iov[0].iov_len = this_param; + iov += 1; } if (state->data_sent < state->num_data) { this_data = MIN(state->num_data - state->data_sent, useable_space - this_param); + iov[0].iov_base = state->data + state->data_sent; + iov[0].iov_len = this_data; + iov += 1; } - vwv = TALLOC_ARRAY(talloc_tos(), uint16_t, wct); - if (vwv == NULL) { - goto fail; - } param_offset += wct * sizeof(uint16_t); DEBUG(10, ("num_setup=%u, max_setup=%u, " @@ -897,209 +990,119 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, break; } - bytes = (uint8_t *)talloc_append_blob( - talloc_tos(), bytes, - data_blob_const(state->param + state->param_sent, this_param)); - if (bytes == NULL) { - goto fail; - } state->param_sent += this_param; - - bytes = (uint8_t *)talloc_append_blob( - talloc_tos(), bytes, - data_blob_const(state->data + state->data_sent, this_data)); - if (bytes == NULL) { - goto fail; - } state->data_sent += this_data; - if ((cmd == SMBtrans) || (cmd == SMBtrans2) || (cmd == SMBnttrans)) { - /* - * Primary request, retrieve our mid - */ - result = cli_request_send(mem_ctx, state->ev, state->cli, - cmd, 0, wct, vwv, 0, - talloc_get_size(bytes), bytes); - if (result == NULL) { - goto fail; - } - cli_req = talloc_get_type_abort(result->private_data, - struct cli_request); - state->mid = cli_req->mid; - state->seqnum = cli_req->seqnum; - } else { - uint16_t num_bytes = talloc_get_size(bytes); - /* - * Secondary request, we have to fix up the mid. Thus we do - * the chain_cork/chain/uncork ourselves. - */ - if (!cli_chain_cork(state->cli, state->ev, - wct * sizeof(uint16_t) + num_bytes + 3)) { - goto fail; - } - result = cli_request_send(mem_ctx, state->ev, state->cli, cmd, - 0, wct, vwv, 0, num_bytes, bytes); - if (result == NULL) { - goto fail; - } - cli_req = talloc_get_type_abort(result->private_data, - struct cli_request); - cli_req->recv_helper.fn = cli_trans_recv_helper; - cli_req->recv_helper.priv = state; - cli_req->mid = state->mid; - cli_chain_uncork(state->cli); - state->seqnum = cli_req->seqnum; - } - - fail: - TALLOC_FREE(frame); - return result; + *pwct = wct; + *piov_count = iov - state->iov; } -static void cli_trans_ship_rest(struct async_req *req, - struct cli_trans_state *state) +static void cli_trans_done(struct tevent_req *subreq); + +struct tevent_req *cli_trans_send( + TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, uint8_t cmd, + const char *pipe_name, uint16_t fid, uint16_t function, int flags, + uint16_t *setup, uint8_t num_setup, uint8_t max_setup, + uint8_t *param, uint32_t num_param, uint32_t max_param, + uint8_t *data, uint32_t num_data, uint32_t max_data) { - struct cli_request *cli_req; + struct tevent_req *req, *subreq; + struct cli_trans_state *state; + int iov_count; + uint8_t wct; - state->secondary_request_ctx = talloc_new(state); - if (state->secondary_request_ctx == NULL) { - async_req_nterror(req, NT_STATUS_NO_MEMORY); - return; + req = tevent_req_create(mem_ctx, &state, struct cli_trans_state); + if (req == NULL) { + return NULL; } - while ((state->param_sent < state->num_param) - || (state->data_sent < state->num_data)) { - struct async_req *subreq; - - subreq = cli_ship_trans(state->secondary_request_ctx, state); - if (subreq == NULL) { - async_req_nterror(req, NT_STATUS_NO_MEMORY); - return; + if ((cmd == SMBtrans) || (cmd == SMBtrans2)) { + if ((num_param > 0xffff) || (max_param > 0xffff) + || (num_data > 0xffff) || (max_data > 0xffff)) { + DEBUG(3, ("Attempt to send invalid trans2 request " + "(setup %u, params %u/%u, data %u/%u)\n", + (unsigned)num_setup, + (unsigned)num_param, (unsigned)max_param, + (unsigned)num_data, (unsigned)max_data)); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } } - cli_req = talloc_get_type_abort(req->private_data, - struct cli_request); - - cli_req->seqnum = state->seqnum; -} - -static NTSTATUS cli_pull_trans(uint8_t *inbuf, - uint8_t wct, uint16_t *vwv, - uint16_t num_bytes, uint8_t *bytes, - uint8_t smb_cmd, bool expect_first_reply, - uint8_t *pnum_setup, uint16_t **psetup, - uint32_t *ptotal_param, uint32_t *pnum_param, - uint32_t *pparam_disp, uint8_t **pparam, - uint32_t *ptotal_data, uint32_t *pnum_data, - uint32_t *pdata_disp, uint8_t **pdata) -{ - uint32_t param_ofs, data_ofs; + /* + * The largest wct will be for nttrans (19+num_setup). Make sure we + * don't overflow state->vwv in cli_trans_format. + */ - if (expect_first_reply) { - if ((wct != 0) || (num_bytes != 0)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - return NT_STATUS_OK; + if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } - switch (smb_cmd) { - case SMBtrans: - case SMBtrans2: - if (wct < 10) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - *ptotal_param = SVAL(vwv + 0, 0); - *ptotal_data = SVAL(vwv + 1, 0); - *pnum_param = SVAL(vwv + 3, 0); - param_ofs = SVAL(vwv + 4, 0); - *pparam_disp = SVAL(vwv + 5, 0); - *pnum_data = SVAL(vwv + 6, 0); - data_ofs = SVAL(vwv + 7, 0); - *pdata_disp = SVAL(vwv + 8, 0); - *pnum_setup = CVAL(vwv + 9, 0); - if (wct < 10 + (*pnum_setup)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - *psetup = vwv + 10; - - break; - case SMBnttrans: - if (wct < 18) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - *ptotal_param = IVAL(vwv, 3); - *ptotal_data = IVAL(vwv, 7); - *pnum_param = IVAL(vwv, 11); - param_ofs = IVAL(vwv, 15); - *pparam_disp = IVAL(vwv, 19); - *pnum_data = IVAL(vwv, 23); - data_ofs = IVAL(vwv, 27); - *pdata_disp = IVAL(vwv, 31); - *pnum_setup = CVAL(vwv, 35); - *psetup = vwv + 18; - break; + state->cli = cli; + state->ev = ev; + state->cmd = cmd; + state->flags = flags; + state->num_rsetup = 0; + state->rsetup = NULL; + ZERO_STRUCT(state->rparam); + ZERO_STRUCT(state->rdata); - default: - return NT_STATUS_INTERNAL_ERROR; + if ((pipe_name != NULL) + && (!convert_string_allocate(state, CH_UNIX, + cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, + pipe_name, strlen(pipe_name) + 1, + &state->pipe_name_conv, + &state->pipe_name_conv_len, true))) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, ev); } + state->fid = fid; /* trans2 */ + state->function = function; /* nttrans */ - /* - * Check for buffer overflows. data_ofs needs to be checked against - * the incoming buffer length, data_disp against the total - * length. Likewise for param_ofs/param_disp. - */ - - if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param) - || trans_oob(*ptotal_param, *pparam_disp, *pnum_param) - || trans_oob(smb_len(inbuf), data_ofs, *pnum_data) - || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } + state->setup = setup; + state->num_setup = num_setup; + state->max_setup = max_setup; - *pparam = (uint8_t *)inbuf + 4 + param_ofs; - *pdata = (uint8_t *)inbuf + 4 + data_ofs; + state->param = param; + state->num_param = num_param; + state->param_sent = 0; + state->rparam.max = max_param; - return NT_STATUS_OK; -} + state->data = data; + state->num_data = num_data; + state->data_sent = 0; + state->rdata.max = max_data; -static NTSTATUS cli_trans_pull_blob(TALLOC_CTX *mem_ctx, - struct trans_recvblob *blob, - uint32_t total, uint32_t thistime, - uint8_t *buf, uint32_t displacement) -{ - if (blob->data == NULL) { - if (total > blob->max) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - blob->total = total; - blob->data = TALLOC_ARRAY(mem_ctx, uint8_t, total); - if (blob->data == NULL) { - return NT_STATUS_NO_MEMORY; - } - } + cli_trans_format(state, &wct, &iov_count); - if (total > blob->total) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + subreq = cli_smb_req_create(state, ev, cli, cmd, 0, wct, state->vwv, + iov_count, state->iov); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - - if (thistime) { - memcpy(blob->data + displacement, buf, thistime); - blob->received += thistime; + state->mid = cli_smb_req_mid(subreq); + if (!cli_smb_req_send(subreq)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, state->ev); } - - return NT_STATUS_OK; + cli_state_seqnum_persistent(cli, state->mid); + tevent_req_set_callback(subreq, cli_trans_done, req); + return req; } -static void cli_trans_recv_helper(struct async_req *req) +static void cli_trans_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - struct cli_trans_state *state = talloc_get_type_abort( - cli_req->recv_helper.priv, struct cli_trans_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_trans_state *state = tevent_req_data( + req, struct cli_trans_state); + NTSTATUS status; + bool sent_all; uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; uint8_t num_setup = 0; uint16_t *setup = NULL; @@ -1111,13 +1114,8 @@ static void cli_trans_recv_helper(struct async_req *req) uint32_t data_disp = 0; uint8_t *param = NULL; uint8_t *data = NULL; - bool sent_all; - NTSTATUS status; - - sent_all = (state->param_sent == state->num_param) - && (state->data_sent == state->num_data); - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes); /* * We can receive something like STATUS_MORE_ENTRIES, so don't use @@ -1125,46 +1123,43 @@ static void cli_trans_recv_helper(struct async_req *req) */ if (NT_STATUS_IS_ERR(status)) { - async_req_nterror(req, status); - return; + goto fail; } + sent_all = ((state->param_sent == state->num_param) + && (state->data_sent == state->num_data)); + status = cli_pull_trans( - (uint8_t *)cli_req->inbuf, wct, vwv, num_bytes, bytes, + cli_smb_inbuf(subreq), wct, vwv, num_bytes, bytes, state->cmd, !sent_all, &num_setup, &setup, &total_param, &num_param, ¶m_disp, ¶m, &total_data, &num_data, &data_disp, &data); - /* - * We can receive something like STATUS_MORE_ENTRIES, so don't use - * !NT_STATUS_IS_OK(status) here. - */ - - if (NT_STATUS_IS_ERR(status)) { - async_req_nterror(req, status); - return; + if (!NT_STATUS_IS_OK(status)) { + goto fail; } if (!sent_all) { - cli_trans_ship_rest(req, state); - return; - } + int iov_count; - /* - * We've just received a real response. This means that we don't need - * the secondary cli_request structures anymore, they have all been - * shipped to the server. - */ - TALLOC_FREE(state->secondary_request_ctx); + TALLOC_FREE(subreq); - if (num_setup != 0) { - TALLOC_FREE(state->rsetup); - state->rsetup = (uint16_t *)TALLOC_MEMDUP( - state, setup, sizeof(uint16_t) * num_setup); - if (state->rsetup == NULL) { - async_req_nterror(req, NT_STATUS_NO_MEMORY); + cli_trans_format(state, &wct, &iov_count); + + subreq = cli_smb_req_create(state, state->ev, state->cli, + state->cmd + 1, 0, wct, state->vwv, + iov_count, state->iov); + if (tevent_req_nomem(subreq, req)) { return; } + cli_smb_req_set_mid(subreq, state->mid); + + if (!cli_smb_req_send(subreq)) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + tevent_req_set_callback(subreq, cli_trans_done, req); + return; } status = cli_trans_pull_blob( @@ -1173,8 +1168,7 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status))); - async_req_nterror(req, status); - return; + goto fail; } status = cli_trans_pull_blob( @@ -1183,149 +1177,39 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status))); - async_req_nterror(req, status); - return; + goto fail; } if ((state->rparam.total == state->rparam.received) && (state->rdata.total == state->rdata.received)) { - async_req_done(req); - } -} - -struct async_req *cli_trans_send( - TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, uint8_t trans_cmd, - const char *pipe_name, uint16_t fid, uint16_t function, int flags, - uint16_t *setup, uint8_t num_setup, uint8_t max_setup, - uint8_t *param, uint32_t num_param, uint32_t max_param, - uint8_t *data, uint32_t num_data, uint32_t max_data) -{ - struct async_req *req; - struct cli_request *cli_req; - struct cli_trans_state *state; - - /* - * We can't use it in a chained request chain, we'd get the offset - * calculations wrong. - */ - - if (cli_in_chain(cli)) { - return NULL; - } - - if ((trans_cmd == SMBtrans) || (trans_cmd == SMBtrans2)) { - if ((num_param > 0xffff) || (max_param > 0xffff) - || (num_data > 0xffff) || (max_data > 0xffff)) { - DEBUG(3, ("Attempt to send invalid trans2 request " - "(setup %u, params %u/%u, data %u/%u)\n", - (unsigned)num_setup, - (unsigned)num_param, (unsigned)max_param, - (unsigned)num_data, (unsigned)max_data)); - return NULL; - } - } - - state = talloc(mem_ctx, struct cli_trans_state); - if (state == NULL) { - goto nomem; - } - - state->cli = cli; - state->ev = ev; - state->cmd = trans_cmd; - state->num_rsetup = 0; - state->rsetup = NULL; - ZERO_STRUCT(state->rparam); - ZERO_STRUCT(state->rdata); - state->secondary_request_ctx = NULL; - - if (trans_cmd == SMBtrans) { - state->pipe_name = talloc_strdup(state, pipe_name); - if (state->pipe_name == NULL) { - goto nomem; - } - } - if (trans_cmd == SMBtrans2) { - state->fid = fid; - } - if (trans_cmd == SMBnttrans) { - state->function = function; - } - - state->flags = flags; - - if (setup != NULL) { - state->setup = (uint16_t *)TALLOC_MEMDUP( - state, setup, sizeof(*setup) * num_setup); - if (state->setup == NULL) { - goto nomem; - } - state->num_setup = num_setup; - } else { - state->setup = NULL; - state->num_setup = 0; - } - - state->max_setup = max_setup; - - if (param != NULL) { - state->param = (uint8_t *)TALLOC_MEMDUP(state, param, - num_param); - if (state->param == NULL) { - goto nomem; - } - state->num_param = num_param; - } else { - state->param = NULL; - state->num_param = 0; - } - - state->param_sent = 0; - state->rparam.max = max_param; - - if (data != NULL) { - state->data = (uint8_t *)TALLOC_MEMDUP(state, data, num_data); - if (state->data == NULL) { - goto nomem; - } - state->num_data = num_data; - } else { - state->data = NULL; - state->num_data = 0; + TALLOC_FREE(subreq); + cli_state_seqnum_remove(state->cli, state->mid); + tevent_req_done(req); + return; } - state->data_sent = 0; - state->rdata.max = max_data; - - req = cli_ship_trans(state, state); - if (req == NULL) { - goto nomem; + if (!cli_smb_req_set_pending(subreq)) { + status = NT_STATUS_NO_MEMORY; + goto fail; } + return; - cli_req = talloc_get_type_abort(req->private_data, struct cli_request); - cli_req->recv_helper.fn = cli_trans_recv_helper; - cli_req->recv_helper.priv = state; - - return req; - - nomem: - TALLOC_FREE(state); - return NULL; + fail: + cli_state_seqnum_remove(state->cli, state->mid); + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); } -NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint16_t **setup, uint8_t *num_setup, uint8_t **param, uint32_t *num_param, uint8_t **data, uint32_t *num_data) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - struct cli_trans_state *state = talloc_get_type_abort( - cli_req->recv_helper.priv, struct cli_trans_state); + struct cli_trans_state *state = tevent_req_data( + req, struct cli_trans_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } @@ -1366,19 +1250,20 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + status = NT_STATUS_INVALID_PARAMETER; goto fail; } ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } @@ -1388,16 +1273,21 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, param, num_param, max_param, data, num_data, max_data); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_trans_recv(req, mem_ctx, rsetup, num_rsetup, rparam, num_rparam, rdata, num_rdata); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 8b45cb4e9c..2a277a2462 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -204,7 +204,7 @@ struct rpc_np_trans_state { uint32_t rdata_len; }; -static void rpc_np_trans_done(struct async_req *subreq); +static void rpc_np_trans_done(struct tevent_req *subreq); static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -214,8 +214,7 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct tevent_req *req; - struct async_req *subreq; + struct tevent_req *req, *subreq; struct rpc_np_trans_state *state; req = tevent_req_create(mem_ctx, &state, struct rpc_np_trans_state); @@ -233,8 +232,7 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_np_trans_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_np_trans_done, req); return req; fail: @@ -242,10 +240,10 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, return NULL; } -static void rpc_np_trans_done(struct async_req *subreq) +static void rpc_np_trans_done(struct tevent_req *subreq) { - struct tevent_req *req = talloc_get_type_abort( - subreq->async.priv, struct tevent_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); struct rpc_np_trans_state *state = tevent_req_data( req, struct rpc_np_trans_state); NTSTATUS status; -- cgit From 95c792b6afe1e4a3176d95eb451b67ba1ce4a380 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 17:42:13 +0200 Subject: Convert cli_session_setup_guest to tevent_req --- source3/include/proto.h | 8 +-- source3/libsmb/cliconnect.c | 108 ++++++++++++++++++++------------ source3/rpc_client/rpc_transport_smbd.c | 25 ++++---- 3 files changed, 86 insertions(+), 55 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b07cecc136..e7593a98fc 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2303,10 +2303,10 @@ NTSTATUS cli_session_setup(struct cli_state *cli, const char *pass, int passlen, const char *ntpass, int ntpasslen, const char *workgroup); -struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli); -NTSTATUS cli_session_setup_guest_recv(struct async_req *req); +struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli); +NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req); bool cli_ulogoff(struct cli_state *cli); struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, struct event_context *ev, diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index aa1ca595a7..6cc090d7c4 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -165,14 +165,30 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) Do a NT1 guest session setup. ****************************************************************************/ -struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli) +struct cli_session_setup_guest_state { + struct cli_state *cli; + uint16_t vwv[16]; +}; + +static void cli_session_setup_guest_done(struct tevent_req *subreq); + +struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) { - struct async_req *result; - uint16_t vwv[13]; + struct tevent_req *req, *subreq; + struct cli_session_setup_guest_state *state; + uint16_t *vwv; uint8_t *bytes; + req = tevent_req_create(mem_ctx, &state, + struct cli_session_setup_guest_state); + if (req == NULL) { + return NULL; + } + state->cli = cli; + vwv = state->vwv; + SCVAL(vwv+0, 0, 0xFF); SCVAL(vwv+0, 1, 0); SSVAL(vwv+1, 0, 0); @@ -186,7 +202,7 @@ struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, SSVAL(vwv+10, 0, 0); SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli)); - bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = talloc_array(state, uint8_t, 0); bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */ NULL); @@ -195,68 +211,78 @@ struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL); bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL); - if (bytes == NULL) { - return NULL; + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); } - result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0, - 13, vwv, 0, talloc_get_size(bytes), bytes); - TALLOC_FREE(bytes); - return result; + subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv, + talloc_get_size(bytes), bytes); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_session_setup_guest_done, req); + return req; } -NTSTATUS cli_session_setup_guest_recv(struct async_req *req) +static void cli_session_setup_guest_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - struct cli_state *cli = cli_req->cli; - uint8_t wct; - uint16_t *vwv; - uint16_t num_bytes; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_session_setup_guest_state *state = tevent_req_data( + req, struct cli_session_setup_guest_state); + struct cli_state *cli = state->cli; + uint32_t num_bytes; + char *inbuf; uint8_t *bytes; uint8_t *p; NTSTATUS status; - if (async_req_is_nterror(req, &status)) { - return status; - } - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - return status; + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; } + inbuf = (char *)cli_smb_inbuf(subreq); p = bytes; - cli->vuid = SVAL(cli_req->inbuf, smb_uid); + cli->vuid = SVAL(inbuf, smb_uid); - p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p, - sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); - p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p, - sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); - p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p, - sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring), + bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring), + bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring), + bytes+num_bytes-p, STR_TERMINATE); if (strstr(cli->server_type, "Samba")) { cli->is_samba = True; } + TALLOC_FREE(subreq); + status = cli_set_username(cli, ""); if (!NT_STATUS_IS_OK(status)) { - return status; + tevent_req_nterror(req, status); + return; } + tevent_req_done(req); +} - return NT_STATUS_OK; +NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } static NTSTATUS cli_session_setup_guest(struct cli_state *cli) { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ @@ -276,13 +302,17 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli) goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_session_setup_guest_recv(req); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index eb64a34d97..bbd9b24a91 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -129,7 +129,7 @@ struct get_anon_ipc_state { }; static void get_anon_ipc_negprot_done(struct async_req *subreq); -static void get_anon_ipc_sesssetup_done(struct async_req *subreq); +static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq); static void get_anon_ipc_tcon_done(struct async_req *subreq); static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, @@ -165,6 +165,7 @@ static void get_anon_ipc_negprot_done(struct async_req *subreq) subreq->async.priv, struct async_req); struct get_anon_ipc_state *state = talloc_get_type_abort( req->private_data, struct get_anon_ipc_state); + struct tevent_req *subreq2; NTSTATUS status; status = cli_negprot_recv(subreq); @@ -174,20 +175,20 @@ static void get_anon_ipc_negprot_done(struct async_req *subreq) return; } - subreq = cli_session_setup_guest_send(state, state->ev, state->cli); - if (async_req_nomem(subreq, req)) { + subreq2 = cli_session_setup_guest_send(state, state->ev, state->cli); + if (async_req_nomem(subreq2, req)) { return; } - subreq->async.fn = get_anon_ipc_sesssetup_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq2, get_anon_ipc_sesssetup_done, req); } -static void get_anon_ipc_sesssetup_done(struct async_req *subreq) +static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct get_anon_ipc_state *state = talloc_get_type_abort( req->private_data, struct get_anon_ipc_state); + struct async_req *subreq2; NTSTATUS status; status = cli_session_setup_guest_recv(subreq); @@ -197,13 +198,13 @@ static void get_anon_ipc_sesssetup_done(struct async_req *subreq) return; } - subreq = cli_tcon_andx_send(state, state->ev, state->cli, + subreq2 = cli_tcon_andx_send(state, state->ev, state->cli, "IPC$", "IPC", NULL, 0); - if (async_req_nomem(subreq, req)) { + if (async_req_nomem(subreq2, req)) { return; } - subreq->async.fn = get_anon_ipc_tcon_done; - subreq->async.priv = req; + subreq2->async.fn = get_anon_ipc_tcon_done; + subreq2->async.priv = req; } static void get_anon_ipc_tcon_done(struct async_req *subreq) -- cgit From 03becb506613b4ec1d365ff2bbd63e53b0847805 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 18:59:56 +0200 Subject: Convert cli_negprot to tevent_req --- source3/include/proto.h | 8 +-- source3/libsmb/cliconnect.c | 104 +++++++++++++++++++++----------- source3/rpc_client/rpc_transport_smbd.c | 14 ++--- 3 files changed, 79 insertions(+), 47 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index e7593a98fc..e3b83491b4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2319,10 +2319,10 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, bool cli_tdis(struct cli_state *cli); void cli_negprot_sendsync(struct cli_state *cli); NTSTATUS cli_negprot(struct cli_state *cli); -struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli); -NTSTATUS cli_negprot_recv(struct async_req *req); +struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli); +NTSTATUS cli_negprot_recv(struct tevent_req *req); bool cli_session_request(struct cli_state *cli, struct nmb_name *calling, struct nmb_name *called); NTSTATUS cli_connect(struct cli_state *cli, diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 6cc090d7c4..17edfdc808 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1491,14 +1491,27 @@ void cli_negprot_sendsync(struct cli_state *cli) Send a negprot command. ****************************************************************************/ -struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli) +struct cli_negprot_state { + struct cli_state *cli; +}; + +static void cli_negprot_done(struct tevent_req *subreq); + +struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) { - struct async_req *result; + struct tevent_req *req, *subreq; + struct cli_negprot_state *state; uint8_t *bytes = NULL; int numprots; + req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state); + if (req == NULL) { + return NULL; + } + state->cli = cli; + if (cli->protocol < PROTOCOL_NT1) cli->use_spnego = False; @@ -1509,51 +1522,54 @@ struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, break; } bytes = (uint8_t *)talloc_append_blob( - talloc_tos(), bytes, data_blob_const(&c, sizeof(c))); - if (bytes == NULL) { - return NULL; + state, bytes, data_blob_const(&c, sizeof(c))); + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); } bytes = smb_bytes_push_str(bytes, false, prots[numprots].name, strlen(prots[numprots].name)+1, NULL); - if (bytes == NULL) { - return NULL; + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); } } - result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0, - talloc_get_size(bytes), bytes); - TALLOC_FREE(bytes); - return result; + subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL, + talloc_get_size(bytes), bytes); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_negprot_done, req); + return req; } -NTSTATUS cli_negprot_recv(struct async_req *req) +static void cli_negprot_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - struct cli_state *cli = cli_req->cli; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_negprot_state *state = tevent_req_data( + req, struct cli_negprot_state); + struct cli_state *cli = state->cli; uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; NTSTATUS status; uint16_t protnum; - if (async_req_is_nterror(req, &status)) { - return status; - } - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - return status; + TALLOC_FREE(subreq); + return; } protnum = SVAL(vwv, 0); if ((protnum >= ARRAY_SIZE(prots)) - || (prots[protnum].prot > cli_req->cli->protocol)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + || (prots[protnum].prot > cli->protocol)) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } cli->protocol = prots[protnum].prot; @@ -1561,7 +1577,8 @@ NTSTATUS cli_negprot_recv(struct async_req *req) if ((cli->protocol < PROTOCOL_NT1) && client_is_signing_mandatory(cli)) { DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n")); - return NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; } if (cli->protocol >= PROTOCOL_NT1) { @@ -1602,14 +1619,18 @@ NTSTATUS cli_negprot_recv(struct async_req *req) /* Fail if server says signing is mandatory and we don't want to support it. */ if (!client_is_signing_allowed(cli)) { DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); - return NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, + NT_STATUS_ACCESS_DENIED); + return; } negotiated_smb_signing = true; } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) { /* Fail if client says signing is mandatory and the server doesn't support it. */ if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); - return NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, + NT_STATUS_ACCESS_DENIED); + return; } negotiated_smb_signing = true; } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) { @@ -1655,41 +1676,52 @@ NTSTATUS cli_negprot_recv(struct async_req *req) if (getenv("CLI_FORCE_ASCII")) cli->capabilities &= ~CAP_UNICODE; - return NT_STATUS_OK; + tevent_req_done(req); +} + +NTSTATUS cli_negprot_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } NTSTATUS cli_negprot(struct cli_state *cli) { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + status = NT_STATUS_INVALID_PARAMETER; goto fail; } ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = cli_negprot_send(frame, ev, cli); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_negprot_recv(req); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index bbd9b24a91..c1cf9fb24e 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -128,7 +128,7 @@ struct get_anon_ipc_state { struct cli_state *cli; }; -static void get_anon_ipc_negprot_done(struct async_req *subreq); +static void get_anon_ipc_negprot_done(struct tevent_req *subreq); static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq); static void get_anon_ipc_tcon_done(struct async_req *subreq); @@ -136,7 +136,8 @@ static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct get_anon_ipc_state *state; if (!async_req_setup(mem_ctx, &result, &state, @@ -151,18 +152,17 @@ static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = get_anon_ipc_negprot_done; - subreq->async.priv = result; + tevent_req_set_callback(subreq, get_anon_ipc_negprot_done, result); return result; fail: TALLOC_FREE(result); return NULL; } -static void get_anon_ipc_negprot_done(struct async_req *subreq) +static void get_anon_ipc_negprot_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct get_anon_ipc_state *state = talloc_get_type_abort( req->private_data, struct get_anon_ipc_state); struct tevent_req *subreq2; -- cgit From 807328ce6d9dea481995a9f6e86f2b60f4ca4c00 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 19:47:18 +0200 Subject: Convert cli_tcon_andx to tevent_req --- source3/include/proto.h | 12 ++-- source3/libsmb/cliconnect.c | 123 ++++++++++++++++++-------------- source3/rpc_client/rpc_transport_smbd.c | 23 +++--- 3 files changed, 85 insertions(+), 73 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index e3b83491b4..b8ea5d6adc 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2308,12 +2308,12 @@ struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, struct cli_state *cli); NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req); bool cli_ulogoff(struct cli_state *cli); -struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const char *share, const char *dev, - const char *pass, int passlen); -NTSTATUS cli_tcon_andx_recv(struct async_req *req); +struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *share, const char *dev, + const char *pass, int passlen); +NTSTATUS cli_tcon_andx_recv(struct tevent_req *req); NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, const char *dev, const char *pass, int passlen); bool cli_tdis(struct cli_state *cli); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 17edfdc808..34c0825c07 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1219,18 +1219,33 @@ bool cli_ulogoff(struct cli_state *cli) Send a tconX. ****************************************************************************/ -struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const char *share, const char *dev, - const char *pass, int passlen) +struct cli_tcon_andx_state { + struct cli_state *cli; + uint16_t vwv[4]; +}; + +static void cli_tcon_andx_done(struct tevent_req *subreq); + +struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *share, const char *dev, + const char *pass, int passlen) { + struct tevent_req *req, *subreq; + struct cli_tcon_andx_state *state; fstring pword; + uint16_t *vwv; char *tmp = NULL; - struct async_req *result; - uint16_t vwv[4]; uint8_t *bytes; + req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state); + if (req == NULL) { + return NULL; + } + state->cli = cli; + vwv = state->vwv; + fstrcpy(cli->share, share); /* in user level security don't send a password now */ @@ -1293,9 +1308,9 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, SSVAL(vwv+3, 0, passlen); if (passlen) { - bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen); + bytes = (uint8_t *)talloc_memdup(state, pword, passlen); } else { - bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = talloc_array(state, uint8_t, 0); } /* @@ -1303,9 +1318,8 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, */ tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s", cli->desthost, share); - if (tmp == NULL) { - TALLOC_FREE(bytes); - return NULL; + if (tevent_req_nomem(tmp, req)) { + return tevent_req_post(req, ev); } bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1, NULL); @@ -1315,60 +1329,52 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, * Add the devicetype */ tmp = talloc_strdup_upper(talloc_tos(), dev); - if (tmp == NULL) { - TALLOC_FREE(bytes); - return NULL; + if (tevent_req_nomem(tmp, req)) { + return tevent_req_post(req, ev); } bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL); TALLOC_FREE(tmp); - if (bytes == NULL) { - return NULL; + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); } - result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0, - 4, vwv, 0, talloc_get_size(bytes), bytes); - TALLOC_FREE(bytes); - return result; + subreq = cli_smb_send(state, ev, cli, SMBtconX, 0, 4, vwv, + talloc_get_size(bytes), bytes); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_tcon_andx_done, req); + return req; access_denied: - { - struct cli_request *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct cli_request)) { - goto fail; - } - if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) { - return result; - } - } - fail: - TALLOC_FREE(result); - return NULL; + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return tevent_req_post(req, ev); } -NTSTATUS cli_tcon_andx_recv(struct async_req *req) +static void cli_tcon_andx_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - struct cli_state *cli = cli_req->cli; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_tcon_andx_state *state = tevent_req_data( + req, struct cli_tcon_andx_state); + struct cli_state *cli = state->cli; + char *inbuf = (char *)cli_smb_inbuf(subreq); uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; NTSTATUS status; - if (async_req_is_nterror(req, &status)) { - return status; - } - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - return status; + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; } - clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring), - num_bytes, STR_TERMINATE|STR_ASCII); + clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes, + STR_TERMINATE|STR_ASCII); if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) { /* almost certainly win95 - enable bug fixes */ @@ -1386,8 +1392,13 @@ NTSTATUS cli_tcon_andx_recv(struct async_req *req) cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0); } - cli->cnum = SVAL(cli_req->inbuf,smb_tid); - return NT_STATUS_OK; + cli->cnum = SVAL(inbuf,smb_tid); + tevent_req_done(req); +} + +NTSTATUS cli_tcon_andx_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, @@ -1395,10 +1406,10 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ @@ -1418,13 +1429,17 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_tcon_andx_recv(req); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index c1cf9fb24e..5a5433fb1c 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -130,7 +130,7 @@ struct get_anon_ipc_state { static void get_anon_ipc_negprot_done(struct tevent_req *subreq); static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq); -static void get_anon_ipc_tcon_done(struct async_req *subreq); +static void get_anon_ipc_tcon_done(struct tevent_req *subreq); static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -165,7 +165,6 @@ static void get_anon_ipc_negprot_done(struct tevent_req *subreq) subreq, struct async_req); struct get_anon_ipc_state *state = talloc_get_type_abort( req->private_data, struct get_anon_ipc_state); - struct tevent_req *subreq2; NTSTATUS status; status = cli_negprot_recv(subreq); @@ -175,11 +174,11 @@ static void get_anon_ipc_negprot_done(struct tevent_req *subreq) return; } - subreq2 = cli_session_setup_guest_send(state, state->ev, state->cli); - if (async_req_nomem(subreq2, req)) { + subreq = cli_session_setup_guest_send(state, state->ev, state->cli); + if (async_req_nomem(subreq, req)) { return; } - tevent_req_set_callback(subreq2, get_anon_ipc_sesssetup_done, req); + tevent_req_set_callback(subreq, get_anon_ipc_sesssetup_done, req); } static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) @@ -188,7 +187,6 @@ static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) subreq, struct async_req); struct get_anon_ipc_state *state = talloc_get_type_abort( req->private_data, struct get_anon_ipc_state); - struct async_req *subreq2; NTSTATUS status; status = cli_session_setup_guest_recv(subreq); @@ -198,19 +196,18 @@ static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) return; } - subreq2 = cli_tcon_andx_send(state, state->ev, state->cli, + subreq = cli_tcon_andx_send(state, state->ev, state->cli, "IPC$", "IPC", NULL, 0); - if (async_req_nomem(subreq2, req)) { + if (async_req_nomem(subreq, req)) { return; } - subreq2->async.fn = get_anon_ipc_tcon_done; - subreq2->async.priv = req; + tevent_req_set_callback(subreq, get_anon_ipc_tcon_done, req); } -static void get_anon_ipc_tcon_done(struct async_req *subreq) +static void get_anon_ipc_tcon_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); NTSTATUS status; status = cli_tcon_andx_recv(subreq); -- cgit From ca7cd350a6ac47b981d6c9a8b671f4c18642a9f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 20:00:58 +0200 Subject: Convert cli_ntcreate to tevent_req --- source3/include/proto.h | 24 ++++---- source3/libsmb/clifile.c | 106 ++++++++++++++++++++++------------ source3/rpc_client/rpc_transport_np.c | 15 ++--- 3 files changed, 88 insertions(+), 57 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b8ea5d6adc..b8353d51c9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2488,18 +2488,18 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, uint32 FileAttributes, uint32 ShareAccess, uint32 CreateDisposition, uint32 CreateOptions, uint8 SecuityFlags); -struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const char *fname, - uint32_t CreatFlags, - uint32_t DesiredAccess, - uint32_t FileAttributes, - uint32_t ShareAccess, - uint32_t CreateDisposition, - uint32_t CreateOptions, - uint8_t SecurityFlags); -NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum); +struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags); +NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum); NTSTATUS cli_ntcreate(struct cli_state *cli, const char *fname, uint32_t CreatFlags, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 0703f04c5f..3d0e3ec957 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -771,22 +771,36 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, return SVAL(cli->inbuf,smb_vwv2 + 1); } -struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const char *fname, - uint32_t CreatFlags, - uint32_t DesiredAccess, - uint32_t FileAttributes, - uint32_t ShareAccess, - uint32_t CreateDisposition, - uint32_t CreateOptions, - uint8_t SecurityFlags) +struct cli_ntcreate_state { + uint16_t vwv[24]; + uint16_t fnum; +}; + +static void cli_ntcreate_done(struct tevent_req *subreq); + +struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags) { - struct async_req *result; + struct tevent_req *req, *subreq; + struct cli_ntcreate_state *state; + uint16_t *vwv; uint8_t *bytes; size_t converted_len; - uint16_t vwv[24]; + + req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state); + if (req == NULL) { + return NULL; + } + vwv = state->vwv; SCVAL(vwv+0, 0, 0xFF); SCVAL(vwv+0, 1, 0); @@ -808,7 +822,7 @@ struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */ SCVAL(vwv+23, 1, SecurityFlags); - bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = talloc_array(state, uint8_t, 0); bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, strlen(fname)+1, &converted_len); @@ -816,41 +830,53 @@ struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, /* sigh. this copes with broken netapp filer behaviour */ bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL); - if (bytes == NULL) { - return NULL; + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); } SIVAL(vwv+2, 1, converted_len); - result = cli_request_send(mem_ctx, ev, cli, SMBntcreateX, 0, - 24, vwv, 0, talloc_get_size(bytes), bytes); - TALLOC_FREE(bytes); - return result; + subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv, + talloc_get_size(bytes), bytes); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_ntcreate_done, req); + return req; } -NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum) +static void cli_ntcreate_done(struct tevent_req *subreq) { + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_ntcreate_state *state = tevent_req_data( + req, struct cli_ntcreate_state); uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; NTSTATUS status; - if (async_req_is_nterror(req, &status)) { - return status; - } - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (wct < 3) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; } + state->fnum = SVAL(vwv+2, 1); + tevent_req_done(req); +} - *pfnum = SVAL(vwv+2, 1); +NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum) +{ + struct cli_ntcreate_state *state = tevent_req_data( + req, struct cli_ntcreate_state); + NTSTATUS status; + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pfnum = state->fnum; return NT_STATUS_OK; } @@ -867,10 +893,10 @@ NTSTATUS cli_ntcreate(struct cli_state *cli, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ @@ -893,13 +919,17 @@ NTSTATUS cli_ntcreate(struct cli_state *cli, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_ntcreate_recv(req, pfid); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return status; } diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 2a277a2462..e6de8396a8 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -278,14 +278,15 @@ struct rpc_transport_np_init_state { struct rpc_transport_np_state *transport_np; }; -static void rpc_transport_np_init_pipe_open(struct async_req *subreq); +static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq); struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, const struct ndr_syntax_id *abstract_syntax) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct rpc_transport_np_init_state *state; if (!async_req_setup(mem_ctx, &result, &state, @@ -315,8 +316,8 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_transport_np_init_pipe_open; - subreq->async.priv = result; + tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, + result); return result; fail: @@ -324,10 +325,10 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, return NULL; } -static void rpc_transport_np_init_pipe_open(struct async_req *subreq) +static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct rpc_transport_np_init_state *state = talloc_get_type_abort( req->private_data, struct rpc_transport_np_init_state); NTSTATUS status; -- cgit From c23ccff13a6e92b37a104845736e5e8cecd27f35 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Mar 2009 09:54:23 +0100 Subject: Convert cli_read_andx to tevent_req --- source3/include/proto.h | 15 +- source3/libsmb/clireadwrite.c | 258 ++++++++++++++++++++-------------- source3/rpc_client/rpc_transport_np.c | 14 +- 3 files changed, 166 insertions(+), 121 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b8353d51c9..d06466def9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2761,11 +2761,16 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, /* The following definitions come from libsmb/clireadwrite.c */ -struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, int fnum, - off_t offset, size_t size); -NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, +struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size, + struct tevent_req **psmbreq); +struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size); +NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, uint8_t **rcvbuf); struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct event_context *ev, diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f2f447b4c9..a59b26f961 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -70,21 +70,25 @@ static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode) return CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; } +struct cli_read_andx_state { + size_t size; + uint16_t vwv[12]; + NTSTATUS status; + size_t received; + uint8_t *buf; +}; -/* - * Send a read&x request - */ +static void cli_read_andx_done(struct tevent_req *subreq); -struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, int fnum, - off_t offset, size_t size) +struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size, + struct tevent_req **psmbreq) { - struct async_req *result; - struct cli_request *req; + struct tevent_req *req, *subreq; + struct cli_read_andx_state *state; bool bigoffset = False; - - uint16_t vwv[12]; uint8_t wct = 10; if (size > cli_read_max_bufsize(cli)) { @@ -94,82 +98,85 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - SCVAL(vwv + 0, 0, 0xFF); - SCVAL(vwv + 0, 1, 0); - SSVAL(vwv + 1, 0, 0); - SSVAL(vwv + 2, 0, fnum); - SIVAL(vwv + 3, 0, offset); - SSVAL(vwv + 5, 0, size); - SSVAL(vwv + 6, 0, size); - SSVAL(vwv + 7, 0, (size >> 16)); - SSVAL(vwv + 8, 0, 0); - SSVAL(vwv + 9, 0, 0); + req = tevent_req_create(mem_ctx, &state, struct cli_read_andx_state); + if (req == NULL) { + return NULL; + } + state->size = size; + + SCVAL(state->vwv + 0, 0, 0xFF); + SCVAL(state->vwv + 0, 1, 0); + SSVAL(state->vwv + 1, 0, 0); + SSVAL(state->vwv + 2, 0, fnum); + SIVAL(state->vwv + 3, 0, offset); + SSVAL(state->vwv + 5, 0, size); + SSVAL(state->vwv + 6, 0, size); + SSVAL(state->vwv + 7, 0, (size >> 16)); + SSVAL(state->vwv + 8, 0, 0); + SSVAL(state->vwv + 9, 0, 0); if ((uint64_t)offset >> 32) { - bigoffset = True; - SIVAL(vwv + 10, 0, + bigoffset = true; + SIVAL(state->vwv + 10, 0, (((uint64_t)offset)>>32) & 0xffffffff); wct += 2; } - result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0, - 0, NULL); - if (result == NULL) { + subreq = cli_smb_req_create(state, ev, cli, SMBreadX, 0, wct, + state->vwv, 0, NULL); + if (subreq == NULL) { + TALLOC_FREE(req); return NULL; } + tevent_req_set_callback(subreq, cli_read_andx_done, req); + *psmbreq = subreq; + return req; +} - req = talloc_get_type_abort(result->private_data, struct cli_request); - - req->data.read.ofs = offset; - req->data.read.size = size; - req->data.read.received = 0; - req->data.read.rcvbuf = NULL; +struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size) +{ + struct tevent_req *req, *subreq; - return result; + req = cli_read_andx_create(mem_ctx, ev, cli, fnum, offset, size, + &subreq); + if ((req == NULL) || !cli_smb_req_send(subreq)) { + TALLOC_FREE(req); + return NULL; + } + return req; } -/* - * Pull the data out of a finished async read_and_x request. rcvbuf is - * talloced from the request, so better make sure that you copy it away before - * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not - * talloc_move it! - */ - -NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, - uint8_t **rcvbuf) +static void cli_read_andx_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_read_andx_state *state = tevent_req_data( + req, struct cli_read_andx_state); + uint8_t *inbuf; uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; - uint8_t *buf; - NTSTATUS status; - size_t size; - - if (async_req_is_nterror(req, &status)) { - return status; - } - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); - - if (NT_STATUS_IS_ERR(status)) { - return status; - } - - if (wct < 12) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + state->status = cli_smb_recv(subreq, 12, &wct, &vwv, &num_bytes, + &bytes); + if (NT_STATUS_IS_ERR(state->status)) { + tevent_req_nterror(req, state->status); + return; } /* size is the number of bytes the server returned. * Might be zero. */ - size = SVAL(vwv + 5, 0); - size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); + state->received = SVAL(vwv + 5, 0); + state->received |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); - if (size > cli_req->data.read.size) { + if (state->received > state->size) { DEBUG(5,("server returned more than we wanted!\n")); - return NT_STATUS_UNEXPECTED_IO_ERROR; + tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR); + return; } /* @@ -177,24 +184,52 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, * bcc field can't be correct. */ - if ((size < 0xffff) && (size > num_bytes)) { + if ((state->received < 0xffff) && (state->received > num_bytes)) { DEBUG(5, ("server announced more bytes than sent\n")); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } - buf = (uint8_t *)smb_base(cli_req->inbuf) + SVAL(vwv+6, 0); + inbuf = cli_smb_inbuf(subreq); + state->buf = (uint8_t *)smb_base(inbuf) + SVAL(vwv+6, 0); - if (trans_oob(smb_len(cli_req->inbuf), SVAL(vwv+6, 0), size) - || (buf < bytes)) { + if (trans_oob(smb_len(inbuf), SVAL(vwv+6, 0), state->received) + || (state->buf < bytes)) { DEBUG(5, ("server returned invalid read&x data offset\n")); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } + tevent_req_done(req); +} - *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0)); - *received = size; +/* + * Pull the data out of a finished async read_and_x request. rcvbuf is + * talloced from the request, so better make sure that you copy it away before + * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not + * talloc_move it! + */ + +NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, + uint8_t **rcvbuf) +{ + struct cli_read_andx_state *state = tevent_req_data( + req, struct cli_read_andx_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *received = state->received; + *rcvbuf = state->buf; return NT_STATUS_OK; } +struct cli_pull_subreq { + struct tevent_req *req; + ssize_t received; + uint8_t *buf; +}; + /* * Parallel read support. * @@ -221,7 +256,7 @@ struct cli_pull_state { * Outstanding requests */ int num_reqs; - struct async_req **reqs; + struct cli_pull_subreq *reqs; /* * For how many bytes did we send requests already? @@ -259,7 +294,7 @@ static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) state->num_reqs, state->top_req); } -static void cli_pull_read_done(struct async_req *read_req); +static void cli_pull_read_done(struct tevent_req *read_req); /* * Prepare an async pull request @@ -308,7 +343,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->num_reqs = MAX(window_size/state->chunk_size, 1); state->num_reqs = MIN(state->num_reqs, cli->max_mux); - state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, + state->reqs = TALLOC_ZERO_ARRAY(state, struct cli_pull_subreq, state->num_reqs); if (state->reqs == NULL) { goto failed; @@ -317,6 +352,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->requested = 0; for (i=0; inum_reqs; i++) { + struct cli_pull_subreq *subreq = &state->reqs[i]; SMB_OFF_T size_left; size_t request_thistime; @@ -328,18 +364,16 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, size_left = size - state->requested; request_thistime = MIN(size_left, state->chunk_size); - state->reqs[i] = cli_read_andx_send( + subreq->req = cli_read_andx_send( state->reqs, ev, cli, fnum, state->start_offset + state->requested, request_thistime); - if (state->reqs[i] == NULL) { + if (subreq->req == NULL) { goto failed; } - - state->reqs[i]->async.fn = cli_pull_read_done; - state->reqs[i]->async.priv = result; - + tevent_req_set_callback(subreq->req, cli_pull_read_done, + result); state->requested += request_thistime; } return result; @@ -354,18 +388,30 @@ failed: * requests if necessary. */ -static void cli_pull_read_done(struct async_req *read_req) +static void cli_pull_read_done(struct tevent_req *subreq) { - struct async_req *pull_req = talloc_get_type_abort( - read_req->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct cli_pull_state *state = talloc_get_type_abort( - pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = talloc_get_type_abort( - read_req->private_data, struct cli_request); + req->private_data, struct cli_pull_state); + struct cli_pull_subreq *pull_subreq = NULL; NTSTATUS status; + int i; + + for (i = 0; i < state->num_reqs; i++) { + pull_subreq = &state->reqs[i]; + if (subreq == pull_subreq->req) { + break; + } + } + if (i == state->num_reqs) { + /* Huh -- received something we did not send?? */ + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } - status = cli_read_andx_recv(read_req, &read_state->data.read.received, - &read_state->data.read.rcvbuf); + status = cli_read_andx_recv(subreq, &pull_subreq->received, + &pull_subreq->buf); if (!NT_STATUS_IS_OK(status)) { async_req_nterror(state->req, status); return; @@ -380,39 +426,36 @@ static void cli_pull_read_done(struct async_req *read_req) * requests. */ - while (state->reqs[state->top_req] != NULL) { - struct cli_request *top_read; + while (state->reqs[state->top_req].req != NULL) { + struct cli_pull_subreq *top_subreq; DEBUG(11, ("cli_pull_read_done: top_req = %d\n", state->top_req)); - if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { + top_subreq = &state->reqs[state->top_req]; + + if (tevent_req_is_in_progress(top_subreq->req)) { DEBUG(11, ("cli_pull_read_done: top request not yet " "done\n")); return; } - top_read = talloc_get_type_abort( - state->reqs[state->top_req]->private_data, - struct cli_request); - DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " - "pushed\n", (int)top_read->data.read.received, + "pushed\n", (int)top_subreq->received, (int)state->pushed)); - status = state->sink((char *)top_read->data.read.rcvbuf, - top_read->data.read.received, - state->priv); + status = state->sink((char *)top_subreq->buf, + top_subreq->received, state->priv); if (!NT_STATUS_IS_OK(status)) { async_req_nterror(state->req, status); return; } - state->pushed += top_read->data.read.received; + state->pushed += top_subreq->received; - TALLOC_FREE(state->reqs[state->top_req]); + TALLOC_FREE(state->reqs[state->top_req].req); if (state->requested < state->size) { - struct async_req *new_req; + struct tevent_req *new_req; SMB_OFF_T size_left; size_t request_thistime; @@ -435,18 +478,17 @@ static void cli_pull_read_done(struct async_req *read_req) if (async_req_nomem(new_req, state->req)) { return; } + tevent_req_set_callback(new_req, cli_pull_read_done, + req); - new_req->async.fn = cli_pull_read_done; - new_req->async.priv = pull_req; - - state->reqs[state->top_req] = new_req; + state->reqs[state->top_req].req = new_req; state->requested += request_thistime; } state->top_req = (state->top_req+1) % state->num_reqs; } - async_req_done(pull_req); + async_req_done(req); } NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index e6de8396a8..cc8f2e17c6 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -119,7 +119,7 @@ struct rpc_np_read_state { ssize_t received; }; -static void rpc_np_read_done(struct async_req *subreq); +static void rpc_np_read_done(struct tevent_req *subreq); static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -128,8 +128,7 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct tevent_req *req; - struct async_req *subreq; + struct tevent_req *req, *subreq; struct rpc_np_read_state *state; req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state); @@ -144,18 +143,17 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_np_read_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_np_read_done, req); return req; fail: TALLOC_FREE(req); return NULL; } -static void rpc_np_read_done(struct async_req *subreq) +static void rpc_np_read_done(struct tevent_req *subreq) { - struct tevent_req *req = talloc_get_type_abort( - subreq->async.priv, struct tevent_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); struct rpc_np_read_state *state = tevent_req_data( req, struct rpc_np_read_state); NTSTATUS status; -- cgit From 17b8d05b624bd87dfe3c996cd10be5a981007bac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 06:33:17 +0200 Subject: Streamline cli_pull sync wrapper --- source3/libsmb/clireadwrite.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index a59b26f961..08b9684f63 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -512,34 +512,43 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; struct async_req *req; - NTSTATUS result = NT_STATUS_NO_MEMORY; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - return NT_STATUS_INVALID_PARAMETER; + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } ev = event_context_init(frame); if (ev == NULL) { - goto nomem; + status = NT_STATUS_NO_MEMORY; + goto fail; } req = cli_pull_send(frame, ev, cli, fnum, start_offset, size, window_size, sink, priv); if (req == NULL) { - goto nomem; + status = NT_STATUS_NO_MEMORY; + goto fail; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (event_loop_once(ev) == -1) { + status = map_nt_error_from_unix(errno); + goto fail; + } } - result = cli_pull_recv(req, received); - nomem: + status = cli_pull_recv(req, received); + fail: TALLOC_FREE(frame); - return result; + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv) -- cgit From 097db28c5d2d1014ffe63430dbe6f944807faa5c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 13:28:18 +0200 Subject: Convert cli_write_andx to tevent_req --- source3/include/proto.h | 20 ++++-- source3/libsmb/clireadwrite.c | 125 ++++++++++++++++++++++++---------- source3/rpc_client/rpc_transport_np.c | 21 +++--- 3 files changed, 110 insertions(+), 56 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index d06466def9..c42c92e755 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2793,12 +2793,20 @@ ssize_t cli_write(struct cli_state *cli, const char *buf, off_t offset, size_t size); ssize_t cli_smbwrite(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size1); -struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, uint16_t fnum, - uint16_t mode, const uint8_t *buf, - off_t offset, size_t size); -NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten); +struct tevent_req *cli_write_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, + uint16_t mode, const uint8_t *buf, + off_t offset, size_t size, + struct tevent_req **reqs_before, + int num_reqs_before, + struct tevent_req **psmbreq); +struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, + uint16_t mode, const uint8_t *buf, + off_t offset, size_t size); +NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten); struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 08b9684f63..3b1af9e5a5 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -795,19 +795,41 @@ ssize_t cli_smbwrite(struct cli_state *cli, * Send a write&x request */ -struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, uint16_t fnum, - uint16_t mode, const uint8_t *buf, - off_t offset, size_t size) +struct cli_write_andx_state { + size_t size; + uint16_t vwv[14]; + size_t written; + uint8_t pad; + struct iovec iov[2]; +}; + +static void cli_write_andx_done(struct tevent_req *subreq); + +struct tevent_req *cli_write_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, + uint16_t mode, const uint8_t *buf, + off_t offset, size_t size, + struct tevent_req **reqs_before, + int num_reqs_before, + struct tevent_req **psmbreq) { + struct tevent_req *req, *subreq; + struct cli_write_andx_state *state; bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0); uint8_t wct = bigoffset ? 14 : 12; size_t max_write = cli_write_max_bufsize(cli, mode); - uint16_t vwv[14]; + uint16_t *vwv; + + req = tevent_req_create(mem_ctx, &state, struct cli_write_andx_state); + if (req == NULL) { + return NULL; + } size = MIN(size, max_write); + vwv = state->vwv; + SCVAL(vwv+0, 0, 0xFF); SCVAL(vwv+0, 1, 0); SSVAL(vwv+1, 0, 0); @@ -820,7 +842,7 @@ struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, SSVAL(vwv+10, 0, size); SSVAL(vwv+11, 0, - cli_wct_ofs(cli) + cli_smb_wct_ofs(reqs_before, num_reqs_before) + 1 /* the wct field */ + wct * 2 /* vwv */ + 2 /* num_bytes field */ @@ -830,37 +852,70 @@ struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, SIVAL(vwv+12, 0, (((uint64_t)offset)>>32) & 0xffffffff); } - return cli_request_send(mem_ctx, ev, cli, SMBwriteX, 0, wct, vwv, - 2, size, buf); + state->pad = 0; + state->iov[0].iov_base = &state->pad; + state->iov[0].iov_len = 1; + state->iov[1].iov_base = CONST_DISCARD(uint8_t *, buf); + state->iov[1].iov_len = size; + + subreq = cli_smb_req_create(state, ev, cli, SMBwriteX, 0, wct, vwv, + 2, state->iov); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_write_andx_done, req); + *psmbreq = subreq; + return req; } -NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten) +struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, + uint16_t mode, const uint8_t *buf, + off_t offset, size_t size) { + struct tevent_req *req, *subreq; + + req = cli_write_andx_create(mem_ctx, ev, cli, fnum, mode, buf, offset, + size, NULL, 0, &subreq); + if ((req == NULL) || !cli_smb_req_send(subreq)) { + TALLOC_FREE(req); + return NULL; + } + return req; +} + +static void cli_write_andx_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_write_andx_state *state = tevent_req_data( + req, struct cli_write_andx_state); uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; - uint8_t *bytes; NTSTATUS status; - size_t written; - if (async_req_is_nterror(req, &status)) { - return status; + status = cli_smb_recv(subreq, 6, &wct, &vwv, NULL, NULL); + if (NT_STATUS_IS_ERR(status)) { + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; } + state->written = SVAL(vwv+2, 0); + state->written |= SVAL(vwv+4, 0)<<16; + tevent_req_done(req); +} - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); +NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten) +{ + struct cli_write_andx_state *state = tevent_req_data( + req, struct cli_write_andx_state); + NTSTATUS status; - if (NT_STATUS_IS_ERR(status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } - - if (wct < 6) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - written = SVAL(vwv+2, 0); - written |= SVAL(vwv+4, 0)<<16; - *pwritten = written; - + *pwritten = state->written; return NT_STATUS_OK; } @@ -875,7 +930,7 @@ struct cli_writeall_state { size_t written; }; -static void cli_writeall_written(struct async_req *req); +static void cli_writeall_written(struct tevent_req *req); static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -886,7 +941,7 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, off_t offset, size_t size) { struct async_req *result; - struct async_req *subreq; + struct tevent_req *subreq; struct cli_writeall_state *state; if (!async_req_setup(mem_ctx, &result, &state, @@ -908,9 +963,7 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - - subreq->async.fn = cli_writeall_written; - subreq->async.priv = result; + tevent_req_set_callback(subreq, cli_writeall_written, result); return result; fail: @@ -918,10 +971,10 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, return NULL; } -static void cli_writeall_written(struct async_req *subreq) +static void cli_writeall_written(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct cli_writeall_state *state = talloc_get_type_abort( req->private_data, struct cli_writeall_state); NTSTATUS status; @@ -956,9 +1009,7 @@ static void cli_writeall_written(struct async_req *subreq) async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } - - subreq->async.fn = cli_writeall_written; - subreq->async.priv = req; + tevent_req_set_callback(subreq, cli_writeall_written, req); } static NTSTATUS cli_writeall_recv(struct async_req *req) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index cc8f2e17c6..730a309acf 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -49,7 +49,7 @@ struct rpc_np_write_state { size_t written; }; -static void rpc_np_write_done(struct async_req *subreq); +static void rpc_np_write_done(struct tevent_req *subreq); static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -58,8 +58,7 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct tevent_req *req; - struct async_req *subreq; + struct tevent_req *req, *subreq; struct rpc_np_write_state *state; req = tevent_req_create(mem_ctx, &state, struct rpc_np_write_state); @@ -72,21 +71,17 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, np_transport->fnum, 8, /* 8 means message mode. */ data, 0, size); - if (subreq == NULL) { - goto fail; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - subreq->async.fn = rpc_np_write_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_np_write_done, req); return req; - fail: - TALLOC_FREE(req); - return NULL; } -static void rpc_np_write_done(struct async_req *subreq) +static void rpc_np_write_done(struct tevent_req *subreq) { - struct tevent_req *req = talloc_get_type_abort( - subreq->async.priv, struct tevent_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); struct rpc_np_write_state *state = tevent_req_data( req, struct rpc_np_write_state); NTSTATUS status; -- cgit From ad695b2525e192a75b54b614a17b662070c904ca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 06:33:24 +0200 Subject: Streamline cli_push sync wrapper --- source3/libsmb/clireadwrite.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 3b1af9e5a5..bb1e2f66c2 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -1216,32 +1216,41 @@ NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; struct async_req *req; - NTSTATUS result = NT_STATUS_NO_MEMORY; + NTSTATUS status = NT_STATUS_OK; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - return NT_STATUS_INVALID_PARAMETER; + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } ev = event_context_init(frame); if (ev == NULL) { - goto nomem; + status = NT_STATUS_NO_MEMORY; + goto fail; } req = cli_push_send(frame, ev, cli, fnum, mode, start_offset, window_size, source, priv); if (req == NULL) { - goto nomem; + status = NT_STATUS_NO_MEMORY; + goto fail; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (event_loop_once(ev) == -1) { + status = map_nt_error_from_unix(errno); + goto fail; + } } - result = cli_push_recv(req); - nomem: + status = cli_push_recv(req); + fail: TALLOC_FREE(frame); - return result; + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } -- cgit From 31910810cf03a463e3728db9e0298ad9f73900f7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Mar 2009 13:46:24 +0200 Subject: Convert cli_close to tevent_req --- source3/include/proto.h | 11 +++++-- source3/libsmb/clifile.c | 86 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 74 insertions(+), 23 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index c42c92e755..557e5f2c71 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2518,9 +2518,14 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, const char *fname, int flags, int share_mode); NTSTATUS cli_open_recv(struct async_req *req, int *fnum); int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode); -struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, int fnum); -NTSTATUS cli_close_recv(struct async_req *req); +struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + struct tevent_req **psubreq); +struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum); +NTSTATUS cli_close_recv(struct tevent_req *req); bool cli_close(struct cli_state *cli, int fnum); bool cli_ftruncate(struct cli_state *cli, int fnum, uint64_t size); NTSTATUS cli_locktype(struct cli_state *cli, int fnum, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 3d0e3ec957..c492f2b01f 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -1137,65 +1137,111 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, Close a file. ****************************************************************************/ -struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, int fnum) -{ +struct cli_close_state { uint16_t vwv[3]; +}; - SSVAL(vwv+0, 0, fnum); - SIVALS(vwv+1, 0, -1); +static void cli_close_done(struct tevent_req *subreq); - return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv, 0, - 0, NULL); +struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + struct tevent_req **psubreq) +{ + struct tevent_req *req, *subreq; + struct cli_close_state *state; + + req = tevent_req_create(mem_ctx, &state, struct cli_close_state); + if (req == NULL) { + return NULL; + } + SSVAL(state->vwv+0, 0, fnum); + SIVALS(state->vwv+1, 0, -1); + + subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv, + 0, NULL); + if (subreq == NULL) { + TALLOC_FREE(req); + return NULL; + } + tevent_req_set_callback(subreq, cli_close_done, req); + *psubreq = subreq; + return req; } -NTSTATUS cli_close_recv(struct async_req *req) +struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum) { - uint8_t wct; - uint16_t *vwv; - uint16_t num_bytes; - uint8_t *bytes; + struct tevent_req *req, *subreq; + + req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq); + if ((req == NULL) || !cli_smb_req_send(subreq)) { + TALLOC_FREE(req); + return NULL; + } + return req; +} + +static void cli_close_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { - return status; + status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } + tevent_req_done(req); +} - return cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); +NTSTATUS cli_close_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } bool cli_close(struct cli_state *cli, int fnum) { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; bool result = false; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + status = NT_STATUS_INVALID_PARAMETER; goto fail; } ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = cli_close_send(frame, ev, cli, fnum); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } result = NT_STATUS_IS_OK(cli_close_recv(req)); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return result; } -- cgit From 025eb40fbc9db7de9c2497390c3d7449a0169cac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 23:17:55 +0200 Subject: Convert cli_open to tevent_req --- source3/include/proto.h | 13 +++-- source3/libsmb/clifile.c | 148 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 50 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 557e5f2c71..514ee68e7a 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2513,10 +2513,15 @@ NTSTATUS cli_ntcreate(struct cli_state *cli, int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess); uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str, size_t str_len, size_t *pconverted_size); -struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, - const char *fname, int flags, int share_mode); -NTSTATUS cli_open_recv(struct async_req *req, int *fnum); +struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, const char *fname, + int flags, int share_mode, + struct tevent_req **psmbreq); +struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, const char *fname, + int flags, int share_mode); +NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum); int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode); struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, struct event_context *ev, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index c492f2b01f..4293828214 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -998,17 +998,33 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, WARNING: if you open with O_WRONLY then getattrE won't work! ****************************************************************************/ -struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, - const char *fname, int flags, int share_mode) +struct cli_open_state { + uint16_t vwv[15]; + int fnum; + struct iovec bytes; +}; + +static void cli_open_done(struct tevent_req *subreq); + +struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, const char *fname, + int flags, int share_mode, + struct tevent_req **psmbreq) { - unsigned openfn = 0; - unsigned accessmode = 0; - uint8_t additional_flags = 0; + struct tevent_req *req, *subreq; + struct cli_open_state *state; + unsigned openfn; + unsigned accessmode; + uint8_t additional_flags; uint8_t *bytes; - uint16_t vwv[15]; - struct async_req *result; + req = tevent_req_create(mem_ctx, &state, struct cli_open_state); + if (req == NULL) { + return NULL; + } + + openfn = 0; if (flags & O_CREAT) { openfn |= (1<<4); } @@ -1037,63 +1053,96 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, accessmode = 0xFF; } - SCVAL(vwv + 0, 0, 0xFF); - SCVAL(vwv + 0, 1, 0); - SSVAL(vwv + 1, 0, 0); - SSVAL(vwv + 2, 0, 0); /* no additional info */ - SSVAL(vwv + 3, 0, accessmode); - SSVAL(vwv + 4, 0, aSYSTEM | aHIDDEN); - SSVAL(vwv + 5, 0, 0); - SIVAL(vwv + 6, 0, 0); - SSVAL(vwv + 8, 0, openfn); - SIVAL(vwv + 9, 0, 0); - SIVAL(vwv + 11, 0, 0); - SIVAL(vwv + 13, 0, 0); + SCVAL(state->vwv + 0, 0, 0xFF); + SCVAL(state->vwv + 0, 1, 0); + SSVAL(state->vwv + 1, 0, 0); + SSVAL(state->vwv + 2, 0, 0); /* no additional info */ + SSVAL(state->vwv + 3, 0, accessmode); + SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN); + SSVAL(state->vwv + 5, 0, 0); + SIVAL(state->vwv + 6, 0, 0); + SSVAL(state->vwv + 8, 0, openfn); + SIVAL(state->vwv + 9, 0, 0); + SIVAL(state->vwv + 11, 0, 0); + SIVAL(state->vwv + 13, 0, 0); + + additional_flags = 0; if (cli->use_oplocks) { /* if using oplocks then ask for a batch oplock via core and extended methods */ additional_flags = FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK; - SSVAL(vwv+2, 0, SVAL(vwv+2, 0) | 6); + SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6); } - bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = talloc_array(state, uint8_t, 0); bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, strlen(fname)+1, NULL); - if (bytes == NULL) { + + if (tevent_req_nomem(bytes, req)) { + return tevent_req_post(req, ev); + } + + state->bytes.iov_base = bytes; + state->bytes.iov_len = talloc_get_size(bytes); + + subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags, + 15, state->vwv, 1, &state->bytes); + if (subreq == NULL) { + TALLOC_FREE(req); return NULL; } + tevent_req_set_callback(subreq, cli_open_done, req); + *psmbreq = subreq; + return req; +} - result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags, - 15, vwv, 0, talloc_get_size(bytes), bytes); - TALLOC_FREE(bytes); - return result; +struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, const char *fname, + int flags, int share_mode) +{ + struct tevent_req *req, *subreq; + + req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode, + &subreq); + if ((req == NULL) || !cli_smb_req_send(subreq)) { + TALLOC_FREE(req); + return NULL; + } + return req; } -NTSTATUS cli_open_recv(struct async_req *req, int *fnum) +static void cli_open_done(struct tevent_req *subreq) { + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_open_state *state = tevent_req_data( + req, struct cli_open_state); uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; - uint8_t *bytes; NTSTATUS status; - if (async_req_is_nterror(req, &status)) { - return status; - } - - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (wct < 3) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; } + state->fnum = SVAL(vwv+2, 0); + tevent_req_done(req); +} - *fnum = SVAL(vwv+2, 0); +NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum) +{ + struct cli_open_state *state = tevent_req_data( + req, struct cli_open_state); + NTSTATUS status; + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *fnum = state->fnum; return NT_STATUS_OK; } @@ -1102,34 +1151,41 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; int result = -1; - if (cli->fd_event != NULL) { + if (cli_has_async_calls(cli)) { /* * Can't use sync call while an async call is in flight */ - cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + status = NT_STATUS_INVALID_PARAMETER; goto fail; } ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = cli_open_send(frame, ev, cli, fname, flags, share_mode); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } cli_open_recv(req, &result); fail: TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } return result; } -- cgit From 86b09e84aefefdb9c06b66f46886f1bad70797a3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 23:20:45 +0200 Subject: Re-add the CHAIN1 test --- source3/script/tests/test_smbtorture_s3.sh | 2 +- source3/torture/torture.c | 81 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh index 842277b357..70c6d34c88 100755 --- a/source3/script/tests/test_smbtorture_s3.sh +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -27,7 +27,7 @@ tests="$tests UNLINK BROWSE ATTR TRANS2 TORTURE " tests="$tests OPLOCK1 OPLOCK2 OPLOCK3" tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3" tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K" -tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE" +tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE CHAIN1" skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN" skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST" diff --git a/source3/torture/torture.c b/source3/torture/torture.c index a4c1721fe6..22e1104d79 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5023,6 +5023,86 @@ static bool subst_test(const char *str, const char *user, const char *domain, return result; } +static void chain1_open_completion(struct tevent_req *req) +{ + int fnum; + NTSTATUS status; + status = cli_open_recv(req, &fnum); + TALLOC_FREE(req); + + d_printf("cli_open_recv returned %s: %d\n", + nt_errstr(status), + NT_STATUS_IS_OK(status) ? fnum : -1); +} + +static void chain1_write_completion(struct tevent_req *req) +{ + size_t written; + NTSTATUS status; + status = cli_write_andx_recv(req, &written); + TALLOC_FREE(req); + + d_printf("cli_write_andx_recv returned %s: %d\n", + nt_errstr(status), + NT_STATUS_IS_OK(status) ? (int)written : -1); +} + +static void chain1_close_completion(struct tevent_req *req) +{ + NTSTATUS status; + bool *done = (bool *)tevent_req_callback_data_void(req); + + status = cli_close_recv(req); + *done = true; + + TALLOC_FREE(req); + + d_printf("cli_close returned %s\n", nt_errstr(status)); +} + +static bool run_chain1(int dummy) +{ + struct cli_state *cli1; + struct event_context *evt = event_context_init(NULL); + struct tevent_req *reqs[3], *smbreqs[3]; + bool done = false; + const char *str = "foobar"; + + printf("starting chain1 test\n"); + if (!torture_open_connection(&cli1, 0)) { + return False; + } + + cli_sockopt(cli1, sockops); + + reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test", + O_CREAT|O_RDWR, 0, &smbreqs[0]); + if (reqs[0] == NULL) return false; + tevent_req_set_callback(reqs[0], chain1_open_completion, NULL); + + + reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0, + (uint8_t *)str, 0, strlen(str)+1, + smbreqs, 1, &smbreqs[1]); + if (reqs[1] == NULL) return false; + tevent_req_set_callback(reqs[1], chain1_write_completion, NULL); + + reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]); + if (reqs[2] == NULL) return false; + tevent_req_set_callback(reqs[2], chain1_close_completion, &done); + + if (!cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs))) { + return false; + } + + while (!done) { + event_loop_once(evt); + } + + torture_close_connection(cli1); + return True; +} + static size_t null_source(uint8_t *buf, size_t n, void *priv) { size_t *to_pull = (size_t *)priv; @@ -5717,6 +5797,7 @@ static struct { {"FDSESS", run_fdsesstest, 0}, { "EATEST", run_eatest, 0}, { "SESSSETUP_BENCH", run_sesssetup_bench, 0}, + { "CHAIN1", run_chain1, 0}, { "WINDOWS-WRITE", run_windows_write, 0}, { "CLI_ECHO", run_cli_echo, 0}, { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, -- cgit From 64067f920405143895b1e39790e9bd2a6e176d00 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Apr 2009 23:28:01 +0200 Subject: Remove async_req based async libsmb infrastructure --- source3/include/async_smb.h | 112 ------ source3/include/client.h | 25 -- source3/libsmb/async_smb.c | 869 -------------------------------------------- 3 files changed, 1006 deletions(-) (limited to 'source3') diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h index adbfc6e5ca..75c8ef1934 100644 --- a/source3/include/async_smb.h +++ b/source3/include/async_smb.h @@ -22,123 +22,11 @@ #include "includes.h" -/** - * struct cli_request is the state holder for an async client request we sent - * to the server. It can consist of more than one struct async_req that we - * have to server if the application did a cli_chain_cork() and - * cli_chain_uncork() - */ - -struct cli_request { - /** - * "prev" and "next" form the doubly linked list in - * cli_state->outstanding_requests - */ - struct cli_request *prev, *next; - - /** - * num_async: How many chained requests do we serve? - */ - int num_async; - - /** - * async: This is the list of chained requests that were queued up by - * cli_request_chain before we sent out this request - */ - struct async_req **async; - - /** - * The client connection for this request - */ - struct cli_state *cli; - - /** - * The enc_state to decrypt the reply - */ - struct smb_trans_enc_state *enc_state; - - /** - * The mid we used for this request. Mainly used to demultiplex on - * receiving replies. - */ - uint16_t mid; - - uint32_t seqnum; - - /** - * The bytes we have to ship to the server - */ - uint8_t *outbuf; - - /** - * How much from "outbuf" did we already send - */ - size_t sent; - - /** - * The reply comes in here. Its intended size is implicit by - * smb_len(), its current size can be read via talloc_get_size() - */ - char *inbuf; - - /** - * Specific requests might add stuff here. Maybe convert this to a - * private_pointer at some point. - */ - union { - struct { - off_t ofs; - size_t size; - ssize_t received; - uint8_t *rcvbuf; - } read; - struct { - DATA_BLOB data; - uint16_t num_echos; - } echo; - } data; - - /** - * For requests that don't follow the strict request/reply pattern - * such as the transaction request family and echo requests it is - * necessary to break the standard procedure in - * handle_incoming_pdu(). For a simple example look at - * cli_echo_recv_helper(). - */ - struct { - void (*fn)(struct async_req *req); - void *priv; - } recv_helper; -}; - -/* - * Ship a new smb request to the server - */ - -struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t smb_command, - uint8_t additional_flags, - uint8_t wct, const uint16_t *vwv, - size_t bytes_alignment, - uint32_t num_bytes, const uint8_t *bytes); - -uint16_t cli_wct_ofs(const struct cli_state *cli); - -bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, - size_t size_hint); -void cli_chain_uncork(struct cli_state *cli); -bool cli_in_chain(struct cli_state *cli); bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command, uint8_t wct, const uint16_t *vwv, size_t bytes_alignment, uint32_t num_bytes, const uint8_t *bytes); -NTSTATUS cli_pull_reply(struct async_req *req, - uint8_t *pwct, uint16_t **pvwv, - uint16_t *pnum_bytes, uint8_t **pbytes); - /* * Fetch an error out of a NBT packet */ diff --git a/source3/include/client.h b/source3/include/client.h index c10d2109d8..3461dfa47a 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -264,31 +264,6 @@ struct cli_state { bool force_dos_errors; bool case_sensitive; /* False by default. */ - /** - * fd_event is around while we have async requests outstanding or are - * building a chained request. - * - * (fd_event!=NULL) && - * ((outstanding_request!=NULL)||(chain_accumulator!=NULL)) - * - * should always be true, as well as the reverse: If both cli_request - * pointers are NULL, no fd_event is around. - */ - struct fd_event *fd_event; - char *evt_inbuf; - - /** - * A linked list of requests that are waiting for a reply - */ - struct cli_request *outstanding_requests; - - /** - * The place to build up the list of chained requests. In CIFS, a - * single cli_request corresponds to a MID and can serve more than one - * chained async_req. - */ - struct cli_request *chain_accumulator; - /* Where (if anywhere) this is mounted under DFS. */ char *dfs_mountpoint; diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 4f88cdbd80..fc1c7f2f62 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -19,9 +19,6 @@ #include "includes.h" -static void cli_state_handler(struct event_context *event_ctx, - struct fd_event *event, uint16 flags, void *p); - /** * Fetch an error out of a NBT packet * @param[in] buf The SMB packet @@ -68,89 +65,6 @@ void cli_set_error(struct cli_state *cli, NTSTATUS status) return; } -/** - * Allocate a new mid - * @param[in] cli The client connection - * @retval The new, unused mid - */ - -static uint16_t cli_new_mid(struct cli_state *cli) -{ - uint16_t result; - struct cli_request *req; - - while (true) { - result = cli->mid++; - if (result == 0) { - continue; - } - - for (req = cli->outstanding_requests; req; req = req->next) { - if (result == req->mid) { - break; - } - } - - if (req == NULL) { - return result; - } - } -} - -/** - * Print an async req that happens to be a cli_request - * @param[in] mem_ctx The TALLOC_CTX to put the result on - * @param[in] req The request to print - * @retval The string representation of "req" - */ - -static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) -{ - char *result = async_req_print(mem_ctx, req); - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - - if (result == NULL) { - return NULL; - } - - return talloc_asprintf_append_buffer( - result, "mid=%d\n", cli_req->mid); -} - -/** - * Destroy a cli_request - * @param[in] req The cli_request to kill - * @retval Can't fail - */ - -static int cli_request_destructor(struct cli_request *req) -{ - if (req->enc_state != NULL) { - common_free_enc_buffer(req->enc_state, (char *)req->outbuf); - } - DLIST_REMOVE(req->cli->outstanding_requests, req); - if (req->cli->outstanding_requests == NULL) { - TALLOC_FREE(req->cli->fd_event); - } - return 0; -} - -/** - * Are there already requests waiting in the chain_accumulator? - * @param[in] cli The cli_state we want to check - * @retval reply :-) - */ - -bool cli_in_chain(struct cli_state *cli) -{ - if (cli->chain_accumulator == NULL) { - return false; - } - - return (cli->chain_accumulator->num_async != 0); -} - /** * @brief Find the smb_cmd offset of the last command pushed * @param[in] buf The buffer we're building up @@ -325,337 +239,6 @@ bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command, return true; } -/** - * @brief Destroy an async_req that is the visible part of a cli_request - * @param[in] req The request to kill - * @retval Return 0 to make talloc happy - * - * This destructor is a bit tricky: Because a cli_request can host more than - * one async_req for chained requests, we need to make sure that the - * "cli_request" that we were part of is correctly destroyed at the right - * time. This is done by NULLing out ourself from the "async" member of our - * "cli_request". If there is none left, then also TALLOC_FREE() the - * cli_request, which was a talloc child of the client connection cli_state. - */ - -static int cli_async_req_destructor(struct async_req *req) -{ - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - int i, pending; - bool found = false; - - pending = 0; - - for (i=0; inum_async; i++) { - if (cli_req->async[i] == req) { - cli_req->async[i] = NULL; - found = true; - } - if (cli_req->async[i] != NULL) { - pending += 1; - } - } - - SMB_ASSERT(found); - - if (pending == 0) { - TALLOC_FREE(cli_req); - } - - return 0; -} - -/** - * @brief Chain up a request - * @param[in] mem_ctx The TALLOC_CTX for the result - * @param[in] ev The event context that will call us back - * @param[in] cli The cli_state we queue the request up for - * @param[in] smb_command The command that we want to issue - * @param[in] additional_flags open_and_x wants to add oplock header flags - * @param[in] wct How many words? - * @param[in] vwv The words, already in network order - * @param[in] bytes_alignment How shall we align "bytes"? - * @param[in] num_bytes How many bytes? - * @param[in] bytes The data the request ships - * - * cli_request_chain() is the core of the SMB request marshalling routine. It - * will create a new async_req structure in the cli->chain_accumulator->async - * array and marshall the smb_cmd, the vwv array and the bytes into - * cli->chain_accumulator->outbuf. - */ - -static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t smb_command, - uint8_t additional_flags, - uint8_t wct, const uint16_t *vwv, - size_t bytes_alignment, - uint32_t num_bytes, - const uint8_t *bytes) -{ - struct async_req **tmp_reqs; - struct cli_request *req; - - req = cli->chain_accumulator; - - tmp_reqs = TALLOC_REALLOC_ARRAY(req, req->async, struct async_req *, - req->num_async + 1); - if (tmp_reqs == NULL) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - req->async = tmp_reqs; - req->num_async += 1; - - req->async[req->num_async-1] = async_req_new(mem_ctx); - if (req->async[req->num_async-1] == NULL) { - DEBUG(0, ("async_req_new failed\n")); - req->num_async -= 1; - return NULL; - } - req->async[req->num_async-1]->private_data = req; - req->async[req->num_async-1]->print = cli_request_print; - talloc_set_destructor(req->async[req->num_async-1], - cli_async_req_destructor); - - if (!smb_splice_chain(&req->outbuf, smb_command, wct, vwv, - bytes_alignment, num_bytes, bytes)) { - goto fail; - } - - return req->async[req->num_async-1]; - - fail: - TALLOC_FREE(req->async[req->num_async-1]); - req->num_async -= 1; - return NULL; -} - -/** - * @brief prepare a cli_state to accept a chain of requests - * @param[in] cli The cli_state we want to queue up in - * @param[in] ev The event_context that will call us back for the socket - * @param[in] size_hint How many bytes are expected, just an optimization - * @retval Did we have enough memory? - * - * cli_chain_cork() sets up a new cli_request in cli->chain_accumulator. If - * cli is used in an async fashion, i.e. if we have outstanding requests, then - * we do not have to create a fd event. If cli is used only with the sync - * helpers, we need to create the fd_event here. - * - * If you want to issue a chained request to the server, do a - * cli_chain_cork(), then do you cli_open_send(), cli_read_and_x_send(), - * cli_close_send() and so on. The async requests that come out of - * cli_xxx_send() are normal async requests with the difference that they - * won't be shipped individually. But the event_context will still trigger the - * req->async.fn to be called on every single request. - * - * You have to take care yourself that you only issue chainable requests in - * the middle of the chain. - */ - -bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, - size_t size_hint) -{ - struct cli_request *req = NULL; - - SMB_ASSERT(cli->chain_accumulator == NULL); - - if (cli->fd == -1) { - DEBUG(10, ("cli->fd closed\n")); - return false; - } - - if (cli->fd_event == NULL) { - SMB_ASSERT(cli->outstanding_requests == NULL); - cli->fd_event = event_add_fd(ev, cli, cli->fd, - EVENT_FD_READ, - cli_state_handler, cli); - if (cli->fd_event == NULL) { - return false; - } - } - - req = talloc(cli, struct cli_request); - if (req == NULL) { - goto fail; - } - req->cli = cli; - - if (size_hint == 0) { - size_hint = 100; - } - req->outbuf = talloc_array(req, uint8_t, smb_wct + size_hint); - if (req->outbuf == NULL) { - goto fail; - } - req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, uint8_t, - smb_wct); - - req->num_async = 0; - req->async = NULL; - - req->enc_state = NULL; - req->recv_helper.fn = NULL; - - SSVAL(req->outbuf, smb_tid, cli->cnum); - cli_setup_packet_buf(cli, (char *)req->outbuf); - - req->mid = cli_new_mid(cli); - - cli->chain_accumulator = req; - - DEBUG(10, ("cli_chain_cork: mid=%d\n", req->mid)); - - return true; - fail: - TALLOC_FREE(req); - if (cli->outstanding_requests == NULL) { - TALLOC_FREE(cli->fd_event); - } - return false; -} - -/** - * Ship a request queued up via cli_request_chain() - * @param[in] cl The connection - */ - -void cli_chain_uncork(struct cli_state *cli) -{ - struct cli_request *req = cli->chain_accumulator; - size_t smblen; - - SMB_ASSERT(req != NULL); - - DLIST_ADD_END(cli->outstanding_requests, req, struct cli_request *); - talloc_set_destructor(req, cli_request_destructor); - - cli->chain_accumulator = NULL; - - SSVAL(req->outbuf, smb_mid, req->mid); - - smblen = talloc_get_size(req->outbuf) - 4; - - smb_setlen((char *)req->outbuf, smblen); - - if (smblen > 0x1ffff) { - /* - * This is a POSIX 14 word large write. Overwrite just the - * size field, the '0xFFSMB' has been set by smb_setlen which - * _smb_setlen_large does not do. - */ - _smb_setlen_large(((char *)req->outbuf), smblen); - } - - cli_calculate_sign_mac(cli, (char *)req->outbuf, &req->seqnum); - - if (cli_encryption_on(cli)) { - NTSTATUS status; - char *enc_buf; - - status = cli_encrypt_message(cli, (char *)req->outbuf, - &enc_buf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Error in encrypting client message. " - "Error %s\n", nt_errstr(status))); - TALLOC_FREE(req); - return; - } - req->outbuf = (uint8_t *)enc_buf; - req->enc_state = cli->trans_enc_state; - } - - req->sent = 0; - - event_fd_set_writeable(cli->fd_event); -} - -/** - * @brief Send a request to the server - * @param[in] mem_ctx The TALLOC_CTX for the result - * @param[in] ev The event context that will call us back - * @param[in] cli The cli_state we queue the request up for - * @param[in] smb_command The command that we want to issue - * @param[in] additional_flags open_and_x wants to add oplock header flags - * @param[in] wct How many words? - * @param[in] vwv The words, already in network order - * @param[in] bytes_alignment How shall we align "bytes"? - * @param[in] num_bytes How many bytes? - * @param[in] bytes The data the request ships - * - * This is the generic routine to be used by the cli_xxx_send routines. - */ - -struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t smb_command, - uint8_t additional_flags, - uint8_t wct, const uint16_t *vwv, - size_t bytes_alignment, - uint32_t num_bytes, const uint8_t *bytes) -{ - struct async_req *result; - bool uncork = false; - - if (cli->chain_accumulator == NULL) { - if (!cli_chain_cork(cli, ev, - wct * sizeof(uint16_t) + num_bytes + 3)) { - DEBUG(1, ("cli_chain_cork failed\n")); - return NULL; - } - uncork = true; - } - - result = cli_request_chain(mem_ctx, ev, cli, smb_command, - additional_flags, wct, vwv, bytes_alignment, - num_bytes, bytes); - - if (result == NULL) { - DEBUG(1, ("cli_request_chain failed\n")); - } - - if (uncork) { - cli_chain_uncork(cli); - } - - return result; -} - -/** - * Calculate the current ofs to wct for requests like write&x - * @param[in] req The smb request we're currently building - * @retval how many bytes offset have we accumulated? - */ - -uint16_t cli_wct_ofs(const struct cli_state *cli) -{ - size_t buf_size; - - if (cli->chain_accumulator == NULL) { - return smb_wct - 4; - } - - buf_size = talloc_get_size(cli->chain_accumulator->outbuf); - - if (buf_size == smb_wct) { - return smb_wct - 4; - } - - /* - * Add alignment for subsequent requests - */ - - if ((buf_size % 4) != 0) { - buf_size += (4 - (buf_size % 4)); - } - - return buf_size - 4; -} - /** * Figure out if there is an andx command behind the current one * @param[in] buf The smb buffer to look at @@ -682,458 +265,6 @@ static bool have_andx_command(const char *buf, uint16_t ofs) return (CVAL(buf, ofs+1) != 0xff); } -/** - * @brief Pull reply data out of a request - * @param[in] req The request that we just received a reply for - * @param[out] pwct How many words did the server send? - * @param[out] pvwv The words themselves - * @param[out] pnum_bytes How many bytes did the server send? - * @param[out] pbytes The bytes themselves - * @retval Was the reply formally correct? - */ - -NTSTATUS cli_pull_reply(struct async_req *req, - uint8_t *pwct, uint16_t **pvwv, - uint16_t *pnum_bytes, uint8_t **pbytes) -{ - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); - uint8_t wct, cmd; - uint16_t num_bytes; - size_t wct_ofs, bytes_offset; - int i, j; - NTSTATUS status; - - for (i = 0; i < cli_req->num_async; i++) { - if (req == cli_req->async[i]) { - break; - } - } - - if (i == cli_req->num_async) { - cli_set_error(cli_req->cli, NT_STATUS_INVALID_PARAMETER); - return NT_STATUS_INVALID_PARAMETER; - } - - /** - * The status we pull here is only relevant for the last reply in the - * chain. - */ - - status = cli_pull_error(cli_req->inbuf); - - if (i == 0) { - if (NT_STATUS_IS_ERR(status) - && !have_andx_command(cli_req->inbuf, smb_wct)) { - cli_set_error(cli_req->cli, status); - return status; - } - wct_ofs = smb_wct; - goto done; - } - - cmd = CVAL(cli_req->inbuf, smb_com); - wct_ofs = smb_wct; - - for (j = 0; j < i; j++) { - if (j < i-1) { - if (cmd == 0xff) { - return NT_STATUS_REQUEST_ABORTED; - } - if (!is_andx_req(cmd)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - } - - if (!have_andx_command(cli_req->inbuf, wct_ofs)) { - /* - * This request was not completed because a previous - * request in the chain had received an error. - */ - return NT_STATUS_REQUEST_ABORTED; - } - - wct_ofs = SVAL(cli_req->inbuf, wct_ofs + 3); - - /* - * Skip the all-present length field. No overflow, we've just - * put a 16-bit value into a size_t. - */ - wct_ofs += 4; - - if (wct_ofs+2 > talloc_get_size(cli_req->inbuf)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - cmd = CVAL(cli_req->inbuf, wct_ofs + 1); - } - - if (!have_andx_command(cli_req->inbuf, wct_ofs) - && NT_STATUS_IS_ERR(status)) { - /* - * The last command takes the error code. All further commands - * down the requested chain will get a - * NT_STATUS_REQUEST_ABORTED. - */ - return status; - } - - done: - wct = CVAL(cli_req->inbuf, wct_ofs); - - bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t); - num_bytes = SVAL(cli_req->inbuf, bytes_offset); - - /* - * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes - * is a 16-bit value. So bytes_offset being size_t should be far from - * wrapping. - */ - - if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf)) - || (bytes_offset > 0xffff)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - *pwct = wct; - *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1); - *pnum_bytes = num_bytes; - *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2; - - return NT_STATUS_OK; -} - -/** - * Decrypt a PDU, check the signature - * @param[in] cli The cli_state that received something - * @param[in] pdu The incoming bytes - * @retval error code - */ - - -static NTSTATUS validate_smb_crypto(struct cli_state *cli, char *pdu, - struct cli_request **_req, - uint16_t *_mid) -{ - NTSTATUS status; - struct cli_request *req = NULL; - uint16_t mid; - - *_req = NULL; - *_mid = 0; - - if ((IVAL(pdu, 4) != 0x424d53ff) /* 0xFF"SMB" */ - && (SVAL(pdu, 4) != 0x45ff)) /* 0xFF"E" */ { - DEBUG(10, ("Got non-SMB PDU\n")); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - if (cli_encryption_on(cli) && CVAL(pdu, 0) == 0) { - uint16_t enc_ctx_num; - - status = get_enc_ctx_num((uint8_t *)pdu, &enc_ctx_num); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("get_enc_ctx_num returned %s\n", - nt_errstr(status))); - return status; - } - - if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) { - DEBUG(10, ("wrong enc_ctx %d, expected %d\n", - enc_ctx_num, - cli->trans_enc_state->enc_ctx_num)); - return NT_STATUS_INVALID_HANDLE; - } - - status = common_decrypt_buffer(cli->trans_enc_state, pdu); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("common_decrypt_buffer returned %s\n", - nt_errstr(status))); - return status; - } - } - - mid = SVAL(pdu, smb_mid); - - for (req = cli->outstanding_requests; req; req = req->next) { - if (req->mid == mid) { - break; - } - } - - if (!req) { - /* oplock breaks are not signed */ - goto done; - } - - if (!cli_check_sign_mac(cli, pdu, req->seqnum+1)) { - DEBUG(10, ("cli_check_sign_mac failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - -done: - *_req = req; - *_mid = mid; - return NT_STATUS_OK; -} - -/** - * A PDU has arrived on cli->evt_inbuf - * @param[in] cli The cli_state that received something - */ - -static void handle_incoming_pdu(struct cli_state *cli) -{ - struct cli_request *req, *next; - uint16_t mid; - size_t raw_pdu_len, buf_len, rest_len; - char *pdu; - int i; - NTSTATUS status; - - int num_async; - - /* - * The encrypted PDU len might differ from the unencrypted one - */ - raw_pdu_len = smb_len(cli->evt_inbuf) + 4; - buf_len = talloc_get_size(cli->evt_inbuf); - rest_len = buf_len - raw_pdu_len; - - if (buf_len == raw_pdu_len) { - /* - * Optimal case: Exactly one PDU was in the socket buffer - */ - pdu = cli->evt_inbuf; - cli->evt_inbuf = NULL; - } - else { - DEBUG(11, ("buf_len = %d, raw_pdu_len = %d, splitting " - "buffer\n", (int)buf_len, (int)raw_pdu_len)); - - if (raw_pdu_len < rest_len) { - /* - * The PDU is shorter, talloc_memdup that one. - */ - pdu = (char *)talloc_memdup( - cli, cli->evt_inbuf, raw_pdu_len); - - memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len, - buf_len - raw_pdu_len); - - cli->evt_inbuf = TALLOC_REALLOC_ARRAY( - NULL, cli->evt_inbuf, char, rest_len); - - if (pdu == NULL) { - status = NT_STATUS_NO_MEMORY; - goto invalidate_requests; - } - } - else { - /* - * The PDU is larger than the rest, talloc_memdup the - * rest - */ - pdu = cli->evt_inbuf; - - cli->evt_inbuf = (char *)talloc_memdup( - cli, pdu + raw_pdu_len, rest_len); - - if (cli->evt_inbuf == NULL) { - status = NT_STATUS_NO_MEMORY; - goto invalidate_requests; - } - } - } - - status = validate_smb_crypto(cli, pdu, &req, &mid); - if (!NT_STATUS_IS_OK(status)) { - goto invalidate_requests; - } - - DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid)); - - if (req == NULL) { - DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid)); - - TALLOC_FREE(pdu); - return; - } - - req->inbuf = talloc_move(req, &pdu); - - /* - * Freeing the last async_req will free the req (see - * cli_async_req_destructor). So make a copy of req->num_async, we - * can't reference it in the last round. - */ - - num_async = req->num_async; - - for (i=0; iasync via its - * destructor cli_async_req_destructor(). - */ - if (req->async[i] != NULL) { - if (req->recv_helper.fn != NULL) { - req->recv_helper.fn(req->async[i]); - } else { - async_req_done(req->async[i]); - } - } - } - return; - - invalidate_requests: - - DEBUG(10, ("handle_incoming_pdu: Aborting with %s\n", - nt_errstr(status))); - - for (req = cli->outstanding_requests; req; req = next) { - next = req->next; - if (req->num_async) { - async_req_nterror(req->async[0], status); - } - } - return; -} - -/** - * fd event callback. This is the basic connection to the socket - * @param[in] event_ctx The event context that called us - * @param[in] event The event that fired - * @param[in] flags EVENT_FD_READ | EVENT_FD_WRITE - * @param[in] p private_data, in this case the cli_state - */ - -static void cli_state_handler(struct event_context *event_ctx, - struct fd_event *event, uint16 flags, void *p) -{ - struct cli_state *cli = (struct cli_state *)p; - struct cli_request *req, *next; - NTSTATUS status; - - DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); - - if (flags & EVENT_FD_WRITE) { - size_t to_send; - ssize_t sent; - - for (req = cli->outstanding_requests; req; req = req->next) { - to_send = smb_len(req->outbuf)+4; - if (to_send > req->sent) { - break; - } - } - - if (req == NULL) { - if (cli->fd_event != NULL) { - event_fd_set_not_writeable(cli->fd_event); - } - return; - } - - sent = sys_send(cli->fd, req->outbuf + req->sent, - to_send - req->sent, 0); - - if (sent < 0) { - status = map_nt_error_from_unix(errno); - goto sock_error; - } - - req->sent += sent; - - if (req->sent == to_send) { - return; - } - } - - if (flags & EVENT_FD_READ) { - int res, available; - size_t old_size, new_size; - char *tmp; - - res = ioctl(cli->fd, FIONREAD, &available); - if (res == -1) { - DEBUG(10, ("ioctl(FIONREAD) failed: %s\n", - strerror(errno))); - status = map_nt_error_from_unix(errno); - goto sock_error; - } - - if (available == 0) { - /* EOF */ - status = NT_STATUS_END_OF_FILE; - goto sock_error; - } - - old_size = talloc_get_size(cli->evt_inbuf); - new_size = old_size + available; - - if (new_size < old_size) { - /* wrap */ - status = NT_STATUS_UNEXPECTED_IO_ERROR; - goto sock_error; - } - - tmp = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, char, - new_size); - if (tmp == NULL) { - /* nomem */ - status = NT_STATUS_NO_MEMORY; - goto sock_error; - } - cli->evt_inbuf = tmp; - - res = sys_recv(cli->fd, cli->evt_inbuf + old_size, available, 0); - if (res == -1) { - DEBUG(10, ("recv failed: %s\n", strerror(errno))); - status = map_nt_error_from_unix(errno); - goto sock_error; - } - - DEBUG(11, ("cli_state_handler: received %d bytes, " - "smb_len(evt_inbuf) = %d\n", (int)res, - smb_len(cli->evt_inbuf))); - - /* recv *might* have returned less than announced */ - new_size = old_size + res; - - /* shrink, so I don't expect errors here */ - cli->evt_inbuf = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, - char, new_size); - - while ((cli->evt_inbuf != NULL) - && ((smb_len(cli->evt_inbuf) + 4) <= new_size)) { - /* - * we've got a complete NBT level PDU in evt_inbuf - */ - handle_incoming_pdu(cli); - new_size = talloc_get_size(cli->evt_inbuf); - } - } - - return; - - sock_error: - - for (req = cli->outstanding_requests; req; req = next) { - int i, num_async; - - next = req->next; - num_async = req->num_async; - - for (i=0; iasync[i], status); - } - } - TALLOC_FREE(cli->fd_event); - close(cli->fd); - cli->fd = -1; -} - #define MAX_SMB_IOV 5 struct cli_smb_state { -- cgit From cb120b4df69d3997e02e0dd2ee4be150c3ce8c8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Apr 2009 14:51:34 +0200 Subject: Never hand out 0xffff as a mid This is used for oplock replies --- source3/libsmb/async_smb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index fc1c7f2f62..1cbf4ae26f 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -300,7 +300,7 @@ static uint16_t cli_alloc_mid(struct cli_state *cli) int i; result = cli->mid++; - if (result == 0) { + if ((result == 0) || (result == 0xffff)) { continue; } -- cgit From 64ce0e4645727be7b493fca54fdf6af91f3f7927 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Apr 2009 16:06:04 +0200 Subject: Add async oplock waiter --- source3/include/async_smb.h | 7 +++ source3/libsmb/async_smb.c | 102 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h index 75c8ef1934..87ddca6677 100644 --- a/source3/include/async_smb.h +++ b/source3/include/async_smb.h @@ -66,4 +66,11 @@ NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv, uint32_t *pnum_bytes, uint8_t **pbytes); +struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli); +NTSTATUS cli_smb_oplock_break_waiter_recv(struct tevent_req *req, + uint16_t *pfnum, + uint8_t *plevel); + #endif diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 1cbf4ae26f..6faf96c207 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -685,6 +685,7 @@ static void cli_smb_received(struct tevent_req *subreq) int num_pending; int i, err; uint16_t mid; + bool oplock_break; received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err); TALLOC_FREE(subreq); @@ -741,11 +742,31 @@ static void cli_smb_received(struct tevent_req *subreq) goto done; } + oplock_break = false; + + if (mid == 0xffff) { + /* + * Paranoia checks that this is really an oplock break request. + */ + oplock_break = (smb_len(inbuf) == 51); /* hdr + 8 words */ + oplock_break &= ((CVAL(inbuf, smb_flg) & FLAG_REPLY) == 0); + oplock_break &= (CVAL(inbuf, smb_com) == SMBlockingX); + oplock_break &= (SVAL(inbuf, smb_vwv6) == 0); + oplock_break &= (SVAL(inbuf, smb_vwv7) == 0); + + if (!oplock_break) { + /* Dump unexpected reply */ + TALLOC_FREE(inbuf); + goto done; + } + } + req = cli->pending[i]; state = tevent_req_data(req, struct cli_smb_state); ev = state->ev; - if (!cli_check_sign_mac(cli, (char *)inbuf, state->seqnum+1)) { + if (!oplock_break /* oplock breaks are not signed */ + && !cli_check_sign_mac(cli, (char *)inbuf, state->seqnum+1)) { DEBUG(10, ("cli_check_sign_mac failed\n")); TALLOC_FREE(inbuf); status = NT_STATUS_ACCESS_DENIED; @@ -1029,3 +1050,82 @@ bool cli_has_async_calls(struct cli_state *cli) return ((tevent_queue_length(cli->outgoing) != 0) || (talloc_array_length(cli->pending) != 0)); } + +struct cli_smb_oplock_break_waiter_state { + uint16_t fnum; + uint8_t level; +}; + +static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq); + +struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) +{ + struct tevent_req *req, *subreq; + struct cli_smb_oplock_break_waiter_state *state; + struct cli_smb_state *smb_state; + + req = tevent_req_create(mem_ctx, &state, + struct cli_smb_oplock_break_waiter_state); + if (req == NULL) { + return NULL; + } + + /* + * Create a fake SMB request that we will never send out. This is only + * used to be set into the pending queue with the right mid. + */ + subreq = cli_smb_req_create(mem_ctx, ev, cli, 0, 0, 0, NULL, 0, NULL); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + smb_state = tevent_req_data(subreq, struct cli_smb_state); + SSVAL(smb_state->header, smb_mid, 0xffff); + + if (!cli_smb_req_set_pending(subreq)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_smb_oplock_break_waiter_done, req); + return req; +} + +static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_smb_oplock_break_waiter_state *state = tevent_req_data( + req, struct cli_smb_oplock_break_waiter_state); + uint8_t wct; + uint16_t *vwv; + uint32_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + status = cli_smb_recv(subreq, 8, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(subreq); + tevent_req_nterror(req, status); + return; + } + state->fnum = SVAL(vwv+2, 0); + state->level = CVAL(vwv+3, 1); + tevent_req_done(req); +} + +NTSTATUS cli_smb_oplock_break_waiter_recv(struct tevent_req *req, + uint16_t *pfnum, + uint8_t *plevel) +{ + struct cli_smb_oplock_break_waiter_state *state = tevent_req_data( + req, struct cli_smb_oplock_break_waiter_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pfnum = state->fnum; + *plevel = state->level; + return NT_STATUS_OK; +} -- cgit From 0c353b57113b02bccaaa3ec09ff9fb1fd8542bd4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Apr 2009 20:41:48 +0200 Subject: Make cli_oplock_ack async --- source3/include/proto.h | 5 ++ source3/libsmb/clioplock.c | 123 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 99 insertions(+), 29 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 514ee68e7a..d76ee08fd2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2644,6 +2644,11 @@ bool cli_message_end(struct cli_state *cli, int grp); /* The following definitions come from libsmb/clioplock.c */ +struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, uint8_t level); +NTSTATUS cli_oplock_ack_recv(struct tevent_req *req); bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level); void cli_oplock_handler(struct cli_state *cli, bool (*handler)(struct cli_state *, int, unsigned char)); diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c index ef8b396461..e3fb66aba0 100644 --- a/source3/libsmb/clioplock.c +++ b/source3/libsmb/clioplock.c @@ -23,38 +23,103 @@ send an ack for an oplock break request ****************************************************************************/ -bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level) +struct cli_oplock_ack_state { + uint16_t vwv[8]; +}; + +static void cli_oplock_ack_done(struct tevent_req *subreq); + +struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, uint8_t level) +{ + struct tevent_req *req, *subreq; + struct cli_oplock_ack_state *state; + + req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);; + if (req == NULL) { + return NULL; + } + SCVAL(state->vwv+0, 0, 0xff); + SCVAL(state->vwv+0, 1, 0); + SSVAL(state->vwv+1, 0, 0); + SSVAL(state->vwv+2, 0, fnum); + SCVAL(state->vwv+3, 0, LOCKING_ANDX_OPLOCK_RELEASE); + SCVAL(state->vwv+3, 1, level); + SIVAL(state->vwv+4, 0, 0); /* timeout */ + SSVAL(state->vwv+6, 0, 0); /* unlockcount */ + SSVAL(state->vwv+7, 0, 0); /* lockcount */ + + subreq = cli_smb_send(state, ev, cli, SMBlockingX, 0, 8, state->vwv, + 0, NULL); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_oplock_ack_done, req); + return req; +} + +static void cli_oplock_ack_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; + + status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} + +NTSTATUS cli_oplock_ack_recv(struct tevent_req *req) { - char *oldbuf = cli->outbuf; - char buf[smb_size+16]; - bool ret; - - cli->outbuf = buf; - - memset(buf,'\0',smb_size); - cli_set_message(buf,8,0,True); - - SCVAL(buf,smb_com,SMBlockingX); - SSVAL(buf,smb_tid, cli->cnum); - cli_setup_packet(cli); - SSVAL(buf,smb_vwv0,0xFF); - SSVAL(buf,smb_vwv1,0); - SSVAL(buf,smb_vwv2,fnum); - if (level == 1) - SSVAL(buf,smb_vwv3,0x102); /* levelII oplock break ack */ - else - SSVAL(buf,smb_vwv3,2); /* exclusive oplock break ack */ - SIVAL(buf,smb_vwv4,0); /* timoeut */ - SSVAL(buf,smb_vwv6,0); /* unlockcount */ - SSVAL(buf,smb_vwv7,0); /* lockcount */ - - ret = cli_send_smb(cli); - - cli->outbuf = oldbuf; - - return ret; + return tevent_req_simple_recv_ntstatus(req); } +bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_oplock_ack_send(frame, ev, cli, fnum, level); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_oplock_ack_recv(req); + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return NT_STATUS_IS_OK(status); +} /**************************************************************************** set the oplock handler for a connection -- cgit From 3084d49cc000dbfeb01d931d737c695dcd392e4a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Apr 2009 20:45:08 +0200 Subject: Add a bad hack to enable level 2 oplocks in torture_open_connection_share --- source3/include/client.h | 2 ++ source3/libsmb/cliconnect.c | 4 ++++ source3/torture/torture.c | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/include/client.h b/source3/include/client.h index 3461dfa47a..c314c9c6a9 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -289,5 +289,7 @@ typedef struct file_info { #define CLI_FULL_CONNECTION_USE_KERBEROS 0x0002 #define CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK 0x0004 #define CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS 0x0008 +#define CLI_FULL_CONNECTION_OPLOCKS 0x0010 +#define CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS 0x0020 #endif /* _CLIENT_H */ diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 34c0825c07..53a812d222 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -2169,6 +2169,10 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, return nt_status; } + cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0); + cli->use_level_II_oplocks = + ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0); + nt_status = cli_session_setup(cli, user, password, pw_len, password, pw_len, domain); if (!NT_STATUS_IS_OK(nt_status)) { diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 22e1104d79..804e772516 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -273,6 +273,10 @@ static bool torture_open_connection_share(struct cli_state **c, if (use_kerberos) flags |= CLI_FULL_CONNECTION_USE_KERBEROS; + if (use_oplocks) + flags |= CLI_FULL_CONNECTION_OPLOCKS; + if (use_level_II_oplocks) + flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS; status = cli_full_connection(c, myname, hostname, NULL, port_to_use, @@ -285,8 +289,6 @@ static bool torture_open_connection_share(struct cli_state **c, return False; } - if (use_oplocks) (*c)->use_oplocks = True; - if (use_level_II_oplocks) (*c)->use_level_II_oplocks = True; (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */ if (do_encrypt) { -- cgit From 1c4027678e7300580cdb4122f19261afedcbad6c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Apr 2009 20:52:04 +0200 Subject: Correct sync wrappers in cli_pipe.c --- source3/rpc_client/cli_pipe.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 6b83c170f5..a8cc33f585 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2291,19 +2291,24 @@ NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; struct tevent_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; + NTSTATUS status = NT_STATUS_OK; ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = rpc_api_pipe_req_send(frame, ev, cli, op_num, in_data); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - tevent_req_poll(req, ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } status = rpc_api_pipe_req_recv(req, mem_ctx, out_data); fail: @@ -2905,19 +2910,24 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; struct tevent_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; + NTSTATUS status = NT_STATUS_OK; ev = event_context_init(frame); if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } req = rpc_pipe_bind_send(frame, ev, cli, auth); if (req == NULL) { + status = NT_STATUS_NO_MEMORY; goto fail; } - tevent_req_poll(req, ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } status = rpc_pipe_bind_recv(req); fail: -- cgit From 12d9765177fc16f7b13e460e1d79c50c256d6fa8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 3 Apr 2009 21:26:14 +0200 Subject: s3-samr: add support for _samr_Connect3() while planning to pass a s4 smbtorture test. Guenther --- source3/rpc_server/srv_samr_nt.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index a4bfe73f1c..7881ca62ea 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -3245,6 +3245,9 @@ NTSTATUS _samr_Connect2(pipes_struct *p, case NDR_SAMR_CONNECT2: fn = "_samr_Connect2"; break; + case NDR_SAMR_CONNECT3: + fn = "_samr_Connect3"; + break; case NDR_SAMR_CONNECT4: fn = "_samr_Connect4"; break; @@ -3289,6 +3292,22 @@ NTSTATUS _samr_Connect2(pipes_struct *p, return nt_status; } +/**************************************************************** + _samr_Connect3 +****************************************************************/ + +NTSTATUS _samr_Connect3(pipes_struct *p, + struct samr_Connect3 *r) +{ + struct samr_Connect2 c; + + c.in.system_name = r->in.system_name; + c.in.access_mask = r->in.access_mask; + c.out.connect_handle = r->out.connect_handle; + + return _samr_Connect2(p, &c); +} + /******************************************************************* _samr_Connect4 ********************************************************************/ @@ -5901,16 +5920,6 @@ NTSTATUS _samr_GetBootKeyInformation(pipes_struct *p, /**************************************************************** ****************************************************************/ -NTSTATUS _samr_Connect3(pipes_struct *p, - struct samr_Connect3 *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - NTSTATUS _samr_RidToSid(pipes_struct *p, struct samr_RidToSid *r) { -- cgit From 651fa0964a6c49a071c28cdb1e4891b1d95d5b09 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 2 Apr 2009 18:33:30 -0700 Subject: s3 oplocks: Refactor level II oplock contention --- source3/include/proto.h | 1 + source3/smbd/oplock.c | 110 +++++++++++++++++++++++------------------------- 2 files changed, 54 insertions(+), 57 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index d76ee08fd2..b677c3d922 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6677,6 +6677,7 @@ void release_file_oplock(files_struct *fsp); bool remove_oplock(files_struct *fsp); bool downgrade_oplock(files_struct *fsp); bool should_notify_deferred_opens(void); +void break_level2_to_none_async(files_struct *fsp); void reply_to_oplock_break_requests(files_struct *fsp); void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx, void *private_data, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6add9f5fc1..98f89ac40c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -344,6 +344,54 @@ static void add_oplock_timeout_handler(files_struct *fsp) } } +void break_level2_to_none_async(files_struct *fsp) +{ + char *break_msg; + + if (fsp->oplock_type == NO_OPLOCK) { + /* We already got a "break to none" message and we've handled + * it. just ignore. */ + DEBUG(3, ("process_oplock_async_level2_break_message: already " + "broken to none, ignoring.\n")); + return; + } + + if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { + /* Don't tell the client, just downgrade. */ + DEBUG(3, ("process_oplock_async_level2_break_message: " + "downgrading fake level 2 oplock.\n")); + remove_oplock(fsp); + return; + } + + /* Ensure we're really at level2 state. */ + SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK); + + DEBUG(10,("process_oplock_async_level2_break_message: sending break " + "to none message for fid %d, file %s\n", fsp->fnum, + fsp->fsp_name)); + + /* Now send a break to none message to our client. */ + break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); + } + + show_msg(break_msg); + if (!srv_send_smb(smbd_server_fd(), + break_msg, false, 0, + IS_CONN_ENCRYPTED(fsp->conn), + NULL)) { + exit_server_cleanly("oplock_break: srv_send_smb failed."); + } + + TALLOC_FREE(break_msg); + + /* Async level2 request, don't send a reply, just remove the oplock. */ + remove_oplock(fsp); + +} + /******************************************************************* This handles the case of a write triggering a break to none message on a level2 oplock. @@ -360,7 +408,6 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx { struct share_mode_entry msg; files_struct *fsp; - char *break_msg; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -375,9 +422,8 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %s: " - "%s/%lu\n", procid_str(debug_ctx(), &src), - file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -389,52 +435,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx return; } - if (fsp->oplock_type == NO_OPLOCK) { - /* We already got a "break to none" message and we've handled it. - * just ignore. */ - DEBUG(3, ("process_oplock_async_level2_break_message: already broken to none, ignoring.\n")); - return; - } - - if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { - /* Don't tell the client, just downgrade. */ - DEBUG(3, ("process_oplock_async_level2_break_message: downgrading fake level 2 oplock.\n")); - remove_oplock(fsp); - return; - } - - /* Ensure we're really at level2 state. */ - SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK); - - DEBUG(10,("process_oplock_async_level2_break_message: sending break to " - "none message for fid %d, file %s\n", - fsp->fnum, - fsp->fsp_name)); - - /* Now send a break to none message to our client. */ - - break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); - if (break_msg == NULL) { - exit_server("Could not talloc break_msg\n"); - } - - /* Need to wait before sending a break message if we sent ourselves this message. */ - if (procid_is_me(&src)) { - wait_before_sending_break(); - } - - show_msg(break_msg); - if (!srv_send_smb(smbd_server_fd(), - break_msg, false, 0, - IS_CONN_ENCRYPTED(fsp->conn), - NULL)) { - exit_server_cleanly("oplock_break: srv_send_smb failed."); - } - - TALLOC_FREE(break_msg); - - /* Async level2 request, don't send a reply, just remove the oplock. */ - remove_oplock(fsp); + break_level2_to_none_async(fsp); } /******************************************************************* @@ -790,13 +791,8 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, */ if (procid_is_me(&share_entry->pid)) { - DATA_BLOB blob = data_blob_const(msg, - MSG_SMB_SHARE_MODE_ENTRY_SIZE); - process_oplock_async_level2_break_message(smbd_messaging_context(), - NULL, - MSG_SMB_ASYNC_LEVEL2_BREAK, - share_entry->pid, - &blob); + wait_before_sending_break(); + break_level2_to_none_async(fsp); } else { messaging_send_buf(smbd_messaging_context(), share_entry->pid, -- cgit From 9d2d07503a17971a63153ecc13fdddb763e614b8 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 2 Apr 2009 18:24:43 -0700 Subject: s3 onefs: Simplify level 2 oplock self-contention This removes all oplock dependence on locking.tdb --- source3/smbd/oplock_onefs.c | 79 +++------------------------------------------ 1 file changed, 5 insertions(+), 74 deletions(-) (limited to 'source3') diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index d4f181fc47..b69d937915 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -550,87 +550,18 @@ static void onefs_semlock_write(int fd, enum level2_contention_type type, * the cluster except the fsp's own level 2 oplock. This lack of * self-contention is a limitation of the current OneFS kernel oplocks * implementation. Luckily it is easy to contend our own level 2 oplock by - * iterating the share mode entries and only breaking the oplock if the pid - * matches our's. + * checking the the fsp's oplock_type. If it's a level2, send a break message + * to the client and remove the oplock. */ static void onefs_contend_level2_oplocks_begin(files_struct *fsp, enum level2_contention_type type) { - int i; - struct share_mode_lock *lck; - /* Take care of level 2 kernel contention. */ onefs_semlock_write(fsp->fh->fd, type, SEMLOCK_LOCK); - /* - * If this file is level II oplocked then we need - * to grab the shared memory lock and inform all - * other files with a level II lock that they need - * to flush their read caches. We keep the lock over - * the shared memory area whilst doing this. - */ - - if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - return; - - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, - NULL); - if (lck == NULL) { - DEBUG(0,("onefs_contend_level2_oplocks_begin: failed to lock " - "share mode entry for file %s.\n", fsp->fsp_name )); - return; - } - - DEBUG(10,("onefs_contend_level2_oplocks_begin: num_share_modes = %d\n", - lck->num_share_modes )); - - for(i = 0; i < lck->num_share_modes; i++) { - struct share_mode_entry *share_entry = &lck->share_modes[i]; - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; - - if (!is_valid_share_mode_entry(share_entry)) { - continue; - } - - DEBUG(10,("onefs_contend_level2_oplocks_begin: " - "share_entry[%i]->op_type == %d\n", - i, share_entry->op_type )); - - if (share_entry->op_type == NO_OPLOCK) { - continue; - } - - /* Paranoia .... */ - if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(0,("onefs_contend_level2_oplocks_begin: PANIC. " - "share mode entry %d is an exlusive " - "oplock !\n", i )); - TALLOC_FREE(lck); - abort(); - } - - share_mode_entry_to_message(msg, share_entry); - - /* - * Only contend our own level 2 oplock. The other processes - * will be get break events from the kernel. - */ - if (procid_is_me(&share_entry->pid)) { - DATA_BLOB blob = data_blob_const(msg, - MSG_SMB_SHARE_MODE_ENTRY_SIZE); - process_oplock_async_level2_break_message( - smbd_messaging_context(), - NULL, - MSG_SMB_ASYNC_LEVEL2_BREAK, - share_entry->pid, - &blob); - } - } - - /* We let the message receivers handle removing the oplock state - in the share mode lock db. */ - - TALLOC_FREE(lck); + /* Take care of level 2 self contention. */ + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + break_level2_to_none_async(fsp); } /** -- cgit From 21b083a647997549e8188c6fc0687fdecfaa4cb3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 7 Apr 2009 01:10:41 +0200 Subject: s3-svcctl: Fix _svcctl_EnumServicesStatusW() crash bug on too small buffer. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 3ca85aa755..848cdc25d0 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -468,9 +468,11 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p, } blob = ndr_push_blob(ndr); + if (blob.length >= r->in.buf_size) { + memcpy(r->out.service, blob.data, r->in.buf_size); + } } - r->out.service = blob.data; *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size; *r->out.services_returned = (uint32)num_services; *r->out.resume_handle = 0x0; -- cgit From d71dec9259366e99beca69fcd9397bd38ed82c71 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 7 Apr 2009 00:40:46 +0200 Subject: s3-libads: avoid NULL talloc context with ads_get_dn(). Guenther --- source3/libads/ldap.c | 16 ++++++++-------- source3/printing/nt_printing.c | 2 +- source3/utils/net_ads.c | 8 ++++---- source3/winbindd/idmap_adex/likewise_cell.c | 2 +- source3/winbindd/idmap_adex/provider_unified.c | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index d274377259..841ea8caae 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1629,7 +1629,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid) } /* substitute the bind-path from the well-known-guid-search result */ - wkn_dn = ads_get_dn(ads, NULL, res); + wkn_dn = ads_get_dn(ads, talloc_tos(), res); if (!wkn_dn) { goto out; } @@ -1731,7 +1731,7 @@ uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name) return kvno; } - dn_string = ads_get_dn(ads, NULL, res); + dn_string = ads_get_dn(ads, talloc_tos(), res); if (!dn_string) { DEBUG(0,("ads_get_kvno: out of memory.\n")); ads_msgfree(ads, res); @@ -1826,7 +1826,7 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin talloc_destroy(ctx); return ret; } - dn_string = ads_get_dn(ads, NULL, res); + dn_string = ads_get_dn(ads, talloc_tos(), res); if (!dn_string) { talloc_destroy(ctx); ads_msgfree(ads, res); @@ -2041,7 +2041,7 @@ ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name, goto done; } - computer_dn = ads_get_dn(ads, NULL, res); + computer_dn = ads_get_dn(ads, talloc_tos(), res); if (!computer_dn) { rc = ADS_ERROR(LDAP_NO_MEMORY); goto done; @@ -3129,7 +3129,7 @@ ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads, char *dn = NULL; - dn = ads_get_dn(ads, NULL, msg); + dn = ads_get_dn(ads, talloc_tos(), msg); if (!dn) { ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_MEMORY); @@ -3483,7 +3483,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) return ADS_ERROR_SYSTEM(ENOENT); } - hostnameDN = ads_get_dn(ads, NULL, (LDAPMessage *)msg); + hostnameDN = ads_get_dn(ads, talloc_tos(), (LDAPMessage *)msg); rc = ldap_delete_ext_s(ads->ldap.ld, hostnameDN, pldap_control, NULL); if (rc) { @@ -3514,7 +3514,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) char *dn = NULL; - if ((dn = ads_get_dn(ads, NULL, msg_sub)) == NULL) { + if ((dn = ads_get_dn(ads, talloc_tos(), msg_sub)) == NULL) { SAFE_FREE(host); TALLOC_FREE(hostnameDN); return ADS_ERROR(LDAP_NO_MEMORY); @@ -3712,7 +3712,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads, goto out; } - dn = ads_get_dn(ads, NULL, res); + dn = ads_get_dn(ads, talloc_tos(), res); if (dn == NULL) { status = ADS_ERROR(LDAP_NO_MEMORY); goto out; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 40d7cd6347..c20171b049 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3357,7 +3357,7 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, printer->info_2->sharename, global_myname()); if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { - prt_dn = ads_get_dn(ads, NULL, res); + prt_dn = ads_get_dn(ads, talloc_tos(), res); if (!prt_dn) { ads_msgfree(ads, res); return WERR_NOMEM; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 8ff0cdfcf4..8e927becbe 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -503,7 +503,7 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv) ads_msgfree(ads, res); status=ads_find_user_acct(ads, &res, argv[0]); if (ADS_ERR_OK(status)) { - userdn = ads_get_dn(ads, NULL, res); + userdn = ads_get_dn(ads, talloc_tos(), res); ads_del_dn(ads, userdn); TALLOC_FREE(userdn); } @@ -598,7 +598,7 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv) ads_destroy(&ads); return -1; } - userdn = ads_get_dn(ads, NULL, res); + userdn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, userdn); TALLOC_FREE(userdn); @@ -757,7 +757,7 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv) ads_destroy(&ads); return -1; } - groupdn = ads_get_dn(ads, NULL, res); + groupdn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, groupdn); TALLOC_FREE(groupdn); @@ -1740,7 +1740,7 @@ static int net_ads_printer_remove(struct net_context *c, int argc, const char ** return -1; } - prt_dn = ads_get_dn(ads, NULL, res); + prt_dn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, prt_dn); TALLOC_FREE(prt_dn); diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c index 7354a367b8..d666d8c01a 100644 --- a/source3/winbindd/idmap_adex/likewise_cell.c +++ b/source3/winbindd/idmap_adex/likewise_cell.c @@ -400,7 +400,7 @@ done: e!=NULL; e = ads_next_entry(c->conn, e)) { - char *dn = ads_get_dn(c->conn, NULL, e); + char *dn = ads_get_dn(c->conn, talloc_tos(), e); DEBUGADD(10,(" dn: %s\n", dn ? dn : "")); TALLOC_FREE(dn); diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c index 9134eb4e64..f9d73f5f95 100644 --- a/source3/winbindd/idmap_adex/provider_unified.c +++ b/source3/winbindd/idmap_adex/provider_unified.c @@ -368,7 +368,7 @@ static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list, LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]); while (e) { - entry_dn = ads_get_dn(ads_list[i], NULL, e); + entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e); BAIL_ON_PTR_ERROR(entry_dn, nt_status); if (check_forest_scope(entry_dn)) { -- cgit From fca02c9154796624958a877d2c92cabd65e9d0e4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 16:19:19 +1100 Subject: s3:smbtorture Convert charcnv torture suite to use push_ucs2_talloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/torture/t_push_ucs2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/torture/t_push_ucs2.c b/source3/torture/t_push_ucs2.c index b9bf87ba54..2bd91dafde 100644 --- a/source3/torture/t_push_ucs2.c +++ b/source3/torture/t_push_ucs2.c @@ -14,16 +14,16 @@ static int check_push_ucs2(const char *orig) int ret; size_t converted_size; - push_ucs2_allocate(&dest, orig, &converted_size); - pull_ucs2_allocate(&orig2, dest, &converted_size); + push_ucs2_talloc(NULL, &dest, orig, &converted_size); + pull_ucs2_talloc(NULL, &orig2, dest, &converted_size); ret = strcmp(orig, orig2); if (ret) { fprintf(stderr, "orig: %s\n", orig); fprintf(stderr, "orig (UNIX -> UCS2 -> UNIX): %s\n", orig2); } - SAFE_FREE(dest); - SAFE_FREE(orig2); + TALLOC_FREE(dest); + TALLOC_FREE(orig2); return ret; } -- cgit From 574a6a8c350a4bab3f42f3f9cfb382db721d69b5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 16:23:27 +1100 Subject: s3:kerberos Rework smb_krb5_unparse_name() to take a talloc context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/includes.h | 7 ++++--- source3/libads/authdata.c | 2 +- source3/libads/kerberos.c | 8 ++++---- source3/libads/kerberos_keytab.c | 27 ++++++++++++++------------- source3/libads/kerberos_verify.c | 6 +++--- source3/libnet/libnet_keytab.c | 32 ++++++++++++++------------------ source3/libsmb/clikrb5.c | 23 ++++++++++++----------- source3/smbd/sesssetup.c | 8 -------- source3/utils/ntlm_auth.c | 6 ++---- 9 files changed, 54 insertions(+), 65 deletions(-) (limited to 'source3') diff --git a/source3/include/includes.h b/source3/include/includes.h index c883e17713..497034b62c 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -901,9 +901,10 @@ krb5_error_code smb_krb5_parse_name(krb5_context context, const char *name, /* in unix charset */ krb5_principal *principal); -krb5_error_code smb_krb5_unparse_name(krb5_context context, - krb5_const_principal principal, - char **unix_name); +krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx, + krb5_context context, + krb5_const_principal principal, + char **unix_name); #ifndef HAVE_KRB5_SET_REAL_TIME krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds); diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 9f0f68ed7b..0032e9e4f6 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -469,7 +469,7 @@ out: data_blob_free(&sesskey1); data_blob_free(&sesskey2); - SAFE_FREE(client_princ_out); + TALLOC_FREE(client_princ_out); return status; } diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 52cb975a6c..c476f59ff5 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -545,7 +545,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, /* look under the old key. If this fails, just use the standard key */ - if (smb_krb5_unparse_name(context, host_princ, &unparsed_name) != 0) { + if (smb_krb5_unparse_name(talloc_tos(), context, host_princ, &unparsed_name) != 0) { return (krb5_principal)NULL; } if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) { @@ -558,7 +558,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, ret_princ = NULL; } - SAFE_FREE(unparsed_name); + TALLOC_FREE(unparsed_name); SAFE_FREE(salt_princ_s); return ret_princ; @@ -603,7 +603,7 @@ bool kerberos_secrets_store_salting_principal(const char *service, goto out; } - if (smb_krb5_unparse_name(context, princ, &unparsed_name) != 0) { + if (smb_krb5_unparse_name(talloc_tos(), context, princ, &unparsed_name) != 0) { goto out; } @@ -623,7 +623,7 @@ bool kerberos_secrets_store_salting_principal(const char *service, SAFE_FREE(key); SAFE_FREE(princ_s); - SAFE_FREE(unparsed_name); + TALLOC_FREE(unparsed_name); if (princ) { krb5_free_principal(context, princ); diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c index 7c028cb78f..4fede259ab 100644 --- a/source3/libads/kerberos_keytab.c +++ b/source3/libads/kerberos_keytab.c @@ -64,7 +64,7 @@ int smb_krb5_kt_add_entry_ext(krb5_context context, while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) { bool compare_name_ok = False; - ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc); + ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &ktprinc); if (ret) { DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_unparse_name failed (%s)\n", error_message(ret))); @@ -91,7 +91,7 @@ int smb_krb5_kt_add_entry_ext(krb5_context context, ktprinc, kt_entry.vno)); } - SAFE_FREE(ktprinc); + TALLOC_FREE(ktprinc); if (compare_name_ok) { if (kt_entry.vno == kvno - 1) { @@ -549,13 +549,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads) } } - TALLOC_FREE( ctx ); - /* Now loop through the keytab and update any other existing entries... */ kvno = (krb5_kvno) ads_get_machine_kvno(ads, machine_name); if (kvno == -1) { DEBUG(1,("ads_keytab_create_default: ads_get_machine_kvno failed to determine the system's kvno.\n")); + TALLOC_FREE(ctx); return -1; } @@ -569,6 +568,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) ret = krb5_init_context(&context); if (ret) { DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret))); + TALLOC_FREE(ctx); return ret; } @@ -599,7 +599,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) if (!found) { goto done; } - oldEntries = SMB_MALLOC_ARRAY(char *, found ); + oldEntries = talloc_array(ctx, char *, found ); if (!oldEntries) { DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n")); ret = -1; @@ -615,7 +615,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) char *p; /* This returns a malloc'ed string in ktprinc. */ - ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc); + ret = smb_krb5_unparse_name(oldEntries, context, kt_entry.principal, &ktprinc); if (ret) { DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret))); goto done; @@ -640,12 +640,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads) break; } if (!strcmp(oldEntries[i], ktprinc)) { - SAFE_FREE(ktprinc); + TALLOC_FREE(ktprinc); break; } } if (i == found) { - SAFE_FREE(ktprinc); + TALLOC_FREE(ktprinc); } } smb_krb5_kt_free_entry(context, &kt_entry); @@ -654,7 +654,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) ret = 0; for (i = 0; oldEntries[i]; i++) { ret |= ads_keytab_add_entry(ads, oldEntries[i]); - SAFE_FREE(oldEntries[i]); + TALLOC_FREE(oldEntries[i]); } krb5_kt_end_seq_get(context, keytab, &cursor); } @@ -662,7 +662,8 @@ int ads_keytab_create_default(ADS_STRUCT *ads) done: - SAFE_FREE(oldEntries); + TALLOC_FREE(oldEntries); + TALLOC_FREE(ctx); { krb5_keytab_entry zero_kt_entry; @@ -728,7 +729,7 @@ int ads_keytab_list(const char *keytab_name) char *etype_s = NULL; krb5_enctype enctype = 0; - ret = smb_krb5_unparse_name(context, kt_entry.principal, &princ_s); + ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &princ_s); if (ret) { goto out; } @@ -739,14 +740,14 @@ int ads_keytab_list(const char *keytab_name) if (ret) { if (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1) { - SAFE_FREE(princ_s); + TALLOC_FREE(princ_s); goto out; } } printf("%3d %s\t\t %s\n", kt_entry.vno, etype_s, princ_s); - SAFE_FREE(princ_s); + TALLOC_FREE(princ_s); SAFE_FREE(etype_s); ret = smb_krb5_kt_free_entry(context, &kt_entry); diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index b903b2a6eb..8502902963 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -192,7 +192,7 @@ static bool ads_keytab_verify_ticket(krb5_context context, } while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) { - ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s); + ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &entry_princ_s); if (ret) { DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n", error_message(ret))); @@ -242,7 +242,7 @@ static bool ads_keytab_verify_ticket(krb5_context context, } /* Free the name we parsed. */ - SAFE_FREE(entry_princ_s); + TALLOC_FREE(entry_princ_s); /* Free the entry we just read. */ smb_krb5_kt_free_entry(context, &kt_entry); @@ -636,7 +636,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, #endif #endif - if ((ret = smb_krb5_unparse_name(context, client_principal, principal))) { + if ((ret = smb_krb5_unparse_name(mem_ctx, context, client_principal, principal))) { DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c index 81956942ca..589d4c2525 100644 --- a/source3/libnet/libnet_keytab.c +++ b/source3/libnet/libnet_keytab.c @@ -144,7 +144,7 @@ static krb5_error_code libnet_keytab_remove_entries(krb5_context context, goto cont; } - ret = smb_krb5_unparse_name(context, kt_entry.principal, + ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &princ_s); if (ret) { DEBUG(5, ("smb_krb5_unparse_name failed (%s)\n", @@ -190,7 +190,7 @@ static krb5_error_code libnet_keytab_remove_entries(krb5_context context, cont: smb_krb5_kt_free_entry(context, &kt_entry); - SAFE_FREE(princ_s); + TALLOC_FREE(princ_s); } ret = krb5_kt_end_seq_get(context, keytab, &cursor); @@ -334,6 +334,8 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c krb5_keyblock *keyp; char *princ_s = NULL; + entry = NULL; + if (kt_entry.vno != kvno) { goto cont; } @@ -344,7 +346,13 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c goto cont; } - ret = smb_krb5_unparse_name(ctx->context, kt_entry.principal, + entry = talloc_zero(mem_ctx, struct libnet_keytab_entry); + if (!entry) { + DEBUG(3, ("talloc failed\n")); + goto fail; + } + + ret = smb_krb5_unparse_name(entry, ctx->context, kt_entry.principal, &princ_s); if (ret) { goto cont; @@ -354,24 +362,14 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c goto cont; } - entry = talloc_zero(mem_ctx, struct libnet_keytab_entry); - if (!entry) { - DEBUG(3, ("talloc failed\n")); - goto fail; - } - - entry->name = talloc_strdup(entry, princ_s); - if (!entry->name) { - DEBUG(3, ("talloc_strdup_failed\n")); - goto fail; - } - entry->principal = talloc_strdup(entry, princ_s); if (!entry->principal) { DEBUG(3, ("talloc_strdup_failed\n")); goto fail; } + entry->name = talloc_move(entry, &princ_s); + entry->password = data_blob_talloc(entry, KRB5_KEY_DATA(keyp), KRB5_KEY_LENGTH(keyp)); if (!entry->password.data) { @@ -382,18 +380,16 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c DEBUG(10, ("found entry\n")); smb_krb5_kt_free_entry(ctx->context, &kt_entry); - SAFE_FREE(princ_s); break; fail: smb_krb5_kt_free_entry(ctx->context, &kt_entry); - SAFE_FREE(princ_s); TALLOC_FREE(entry); break; cont: smb_krb5_kt_free_entry(ctx->context, &kt_entry); - SAFE_FREE(princ_s); + TALLOC_FREE(entry); continue; } diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 4ab31374e2..aa98d7668f 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -56,12 +56,12 @@ static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context, char *utf8_name; size_t converted_size; - if (!push_utf8_allocate(&utf8_name, name, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) { return ENOMEM; } ret = krb5_parse_name(context, utf8_name, principal); - SAFE_FREE(utf8_name); + TALLOC_FREE(utf8_name); return ret; } @@ -79,24 +79,25 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context, size_t converted_size; *principal = NULL; - if (!push_utf8_allocate(&utf8_name, name, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) { return ENOMEM; } ret = krb5_parse_name_norealm(context, utf8_name, principal); - SAFE_FREE(utf8_name); + TALLOC_FREE(utf8_name); return ret; } #endif /************************************************************** krb5_parse_name that returns a UNIX charset name. Must - be freed with normal free() call. + be freed with talloc_free() call. **************************************************************/ - krb5_error_code smb_krb5_unparse_name(krb5_context context, - krb5_const_principal principal, - char **unix_name) +krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx, + krb5_context context, + krb5_const_principal principal, + char **unix_name) { krb5_error_code ret; char *utf8_name; @@ -108,7 +109,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context, return ret; } - if (!pull_utf8_allocate(unix_name, utf8_name, &converted_size)) { + if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) { krb5_free_unparsed_name(context, utf8_name); return ENOMEM; } @@ -1081,10 +1082,10 @@ get_key_from_keytab(krb5_context context, } if ( DEBUGLEVEL >= 10 ) { - if (smb_krb5_unparse_name(context, server, &name) == 0) { + if (smb_krb5_unparse_name(talloc_tos(), context, server, &name) == 0) { DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", kvno, enctype, name)); - SAFE_FREE(name); + TALLOC_FREE(name); } } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e8878a29ab..d524f21817 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -333,7 +333,6 @@ static void reply_spnego_kerberos(struct smb_request *req, DEBUG(3,("Doesn't look like a valid principal\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); - SAFE_FREE(client); talloc_destroy(mem_ctx); reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE)); return; @@ -355,7 +354,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); data_blob_free(&session_key); - SAFE_FREE(client); talloc_destroy(mem_ctx); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); @@ -445,7 +443,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !pw ) { DEBUG(1,("Username %s is invalid on this system\n", user)); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -471,7 +468,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -485,7 +481,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_pw failed: %s!\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -513,7 +508,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(10,("failed to create local token: %s\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE( mem_ctx ); @@ -541,8 +535,6 @@ static void reply_spnego_kerberos(struct smb_request *req, nullblob, client); - SAFE_FREE(client); - reply_outbuf(req, 4, 0); SSVAL(req->outbuf,smb_uid,sess_vuid); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 9bc0c60b7b..7899bd0d07 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1251,8 +1251,6 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, &principal, &pac_data, &ap_rep, &session_key, True); - talloc_destroy(mem_ctx); - /* Now in "principal" we have the name we are authenticated as. */ @@ -1274,9 +1272,9 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, user = SMB_STRDUP(principal); data_blob_free(&ap_rep); - - SAFE_FREE(principal); } + + TALLOC_FREE(mem_ctx); } #endif -- cgit From 042aaffabf602560877558ac167c69257862b124 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 18:04:35 +1100 Subject: s3:smbldap convert the easy cases to push_utf8_talloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/lib/smbldap.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 1dfb02035d..4f54f9ad58 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1228,7 +1228,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, ZERO_STRUCT(ldap_state->last_rebind); } - if (!push_utf8_allocate(&utf8_filter, filter, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) { return LDAP_NO_MEMORY; } @@ -1276,7 +1276,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, } } - SAFE_FREE(utf8_filter); + TALLOC_FREE(utf8_filter); /* Teardown timeout. */ CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); @@ -1400,7 +1400,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at DEBUG(5,("smbldap_modify: dn => [%s]\n", dn )); - if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) { return LDAP_NO_MEMORY; } @@ -1428,7 +1428,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at } } - SAFE_FREE(utf8_dn); + TALLOC_FREE(utf8_dn); return rc; } @@ -1444,7 +1444,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs DEBUG(5,("smbldap_add: dn => [%s]\n", dn )); - if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) { return LDAP_NO_MEMORY; } @@ -1472,7 +1472,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs } } - SAFE_FREE(utf8_dn); + TALLOC_FREE(utf8_dn); return rc; } @@ -1488,7 +1488,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) DEBUG(5,("smbldap_delete: dn => [%s]\n", dn )); - if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) { + if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) { return LDAP_NO_MEMORY; } @@ -1516,7 +1516,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) } } - SAFE_FREE(utf8_dn); + TALLOC_FREE(utf8_dn); return rc; } -- cgit From 785c19182ba7c0cc15502ee89f2c3ca1cfb1c5e7 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 7 Apr 2009 09:49:55 -0700 Subject: s3 oplocks: Add back procid_str to debug message --- source3/smbd/oplock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 98f89ac40c..b937e8e07d 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -422,8 +422,9 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %s: " + "%s/%lu\n", procid_str(debug_ctx(), &src), + file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); -- cgit From 161bd7f78fd10e4f850dc3ef1ba3df53c43eae30 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 7 Apr 2009 00:56:50 +0000 Subject: s3 onefs: Fix case-insensitivity for mangled names onefs_get_real_filename needs to demangle the filename before doing the case-insensitive estat --- source3/modules/vfs_onefs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3') diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c index ad59c2b32d..e4a0febbec 100644 --- a/source3/modules/vfs_onefs.c +++ b/source3/modules/vfs_onefs.c @@ -153,10 +153,21 @@ static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path, char **found_name) { SMB_STRUCT_STAT sb; + struct connection_struct *conn = handle->conn; struct stat_extra se; int result; + char *unmangled_name = NULL; char *full_name = NULL; + /* First demangle the name if necessary. */ + if (!conn->case_sensitive && mangle_is_mangled(name, conn->params) && + mangle_lookup_name_from_8_3(mem_ctx, name, &unmangled_name, + conn->params)) { + /* Name is now unmangled. */ + name = unmangled_name; + } + + /* Do the case insensitive stat. */ ZERO_STRUCT(se); se.se_version = ESTAT_CURRENT_VERSION; se.se_flags = ESTAT_CASE_INSENSITIVE | ESTAT_SYMLINK_NOFOLLOW; @@ -184,6 +195,7 @@ static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path, done: TALLOC_FREE(full_name); + TALLOC_FREE(unmangled_name); return result; } -- cgit From 6343cab3086f5795c8428eddcb966ba8b72d3511 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 7 Apr 2009 19:58:14 +0200 Subject: s3/smbconf_reg: Fix typo. Karolin --- source3/lib/smbconf/smbconf_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/smbconf/smbconf_reg.c b/source3/lib/smbconf/smbconf_reg.c index ae6a41151d..0ecac97575 100644 --- a/source3/lib/smbconf/smbconf_reg.c +++ b/source3/lib/smbconf/smbconf_reg.c @@ -193,7 +193,7 @@ static WERROR smbconf_reg_set_value(struct registry_key *key, if (!strequal(subkeyname, GLOBAL_NAME) && lp_parameter_is_global(valname)) { - DEBUG(5, ("Global paramter '%s' not allowed in " + DEBUG(5, ("Global parameter '%s' not allowed in " "service definition ('%s').\n", canon_valname, subkeyname)); werr = WERR_INVALID_PARAM; -- cgit From a103222e0b679d68684681c871ac912f279afc1b Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 7 Apr 2009 19:58:47 +0200 Subject: s3/gpo_ldap: Fix typo. Karolin --- source3/libgpo/gpo_ldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/libgpo/gpo_ldap.c b/source3/libgpo/gpo_ldap.c index 882804b09a..716b8729c3 100644 --- a/source3/libgpo/gpo_ldap.c +++ b/source3/libgpo/gpo_ldap.c @@ -453,7 +453,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads, } /**************************************************************** - get a GROUP_POLICY_OBJECT structure based on different input paramters + get a GROUP_POLICY_OBJECT structure based on different input parameters ****************************************************************/ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads, -- cgit From 4458809597ff4362a653ea5469c5237bbe2a0531 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 7 Apr 2009 20:00:47 +0200 Subject: s3/loadparm: Fiy typos. Karolin --- source3/param/loadparm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 8da1f6348f..4b14b80339 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -885,7 +885,7 @@ static const struct enum_list enum_kerberos_method[] = { /* Note: We do not initialise the defaults union - it is not allowed in ANSI C * - * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit + * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit * screen in SWAT. This is used to exclude parameters as well as to squash all * parameters that have been duplicated by pseudonyms. * @@ -894,7 +894,7 @@ static const struct enum_list enum_kerberos_method[] = { * Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in * respective views. * - * NOTE2: Handling of duplicated (synonym) paramters: + * NOTE2: Handling of duplicated (synonym) parameters: * Only the first occurance of a parameter should be enabled by FLAG_BASIC * and/or FLAG_ADVANCED. All duplicates following the first mention should be * set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred -- cgit From 5fff53882002bf5378690ddeb8251e2c99490266 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 19 Mar 2009 19:11:15 +1100 Subject: s3:charcnv Remove unused ucs2_to_unistr2() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 1 - source3/lib/util_unistr.c | 46 ---------------------------------------------- 2 files changed, 47 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b677c3d922..788f33ff71 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1602,7 +1602,6 @@ smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p); smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins); int unistrlen(uint16 *s); int unistrcpy(uint16 *dst, uint16 *src); -UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src); int toupper_ascii(int c); int tolower_ascii(int c); int isupper_ascii(int c); diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 840e8e06da..178bbc7e94 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -1003,52 +1003,6 @@ int unistrcpy(uint16 *dst, uint16 *src) return num_wchars; } -/** - * Samba ucs2 type to UNISTR2 conversion - * - * @param ctx Talloc context to create the dst strcture (if null) and the - * contents of the unicode string. - * @param dst UNISTR2 destination. If equals null, then it's allocated. - * @param src smb_ucs2_t source. - * @param max_len maximum number of unicode characters to copy. If equals - * null, then null-termination of src is taken - * - * @return copied UNISTR2 destination - **/ - -UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) -{ - size_t len; - - if (!src) { - return NULL; - } - - len = strlen_w(src); - - /* allocate UNISTR2 destination if not given */ - if (!dst) { - dst = TALLOC_P(ctx, UNISTR2); - if (!dst) - return NULL; - } - if (!dst->buffer) { - dst->buffer = TALLOC_ARRAY(ctx, uint16, len + 1); - if (!dst->buffer) - return NULL; - } - - /* set UNISTR2 parameters */ - dst->uni_max_len = len + 1; - dst->offset = 0; - dst->uni_str_len = len; - - /* copy the actual unicode string */ - strncpy_w(dst->buffer, src, dst->uni_max_len); - - return dst; -} - /************************************************************* ascii only toupper - saves the need for smbd to be in C locale. *************************************************************/ -- cgit From 80163b5ac5bfff3698aeb9c5c43a2cc94947055c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 19 Mar 2009 19:14:36 +1100 Subject: s3:charcnv Remove unused unistr2 functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Natrually, the hard work to make these unsued was done by GD, not me :-) Andrew Bartlett Signed-off-by: Günther Deschner --- source3/include/proto.h | 5 -- source3/lib/util_unistr.c | 116 ---------------------------------------------- 2 files changed, 121 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 788f33ff71..d5c11faf56 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1560,13 +1560,8 @@ int rpcstr_pull_talloc(TALLOC_CTX *ctx, void *src, int src_len, int flags); -int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src); -char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src); int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags); int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src); -void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen); -char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str); -const char *unistr2_static(const UNISTR2 *str); smb_ucs2_t toupper_w(smb_ucs2_t val); smb_ucs2_t tolower_w( smb_ucs2_t val ); bool islower_w(smb_ucs2_t c); diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 178bbc7e94..3a6971dcce 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -291,64 +291,6 @@ int rpcstr_pull_talloc(TALLOC_CTX *ctx, } -/* Copy a string from a unistr2 source to internal samba format - destination. Use this instead of direct calls to rpcstr_pull() to avoid - having to determine whether the source string is null terminated. */ - -int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src) -{ - return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring), - src->uni_str_len * 2, 0); -} - -/* Helper function to return a talloc'ed string. I have implemented it with a - * copy because I don't really know how pull_ucs2 and friends calculate the - * target size. If this turns out to be a major bottleneck someone with deeper - * multi-byte knowledge needs to revisit this. - * I just did (JRA :-). No longer uses copy. - * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would - * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c. - */ - -char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src) -{ - char *dest = NULL; - size_t dest_len; - - if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src->buffer, - src->uni_str_len * 2, (void *)&dest, - &dest_len, true)) - { - return NULL; - } - - /* Ensure we're returning a null terminated string. */ - if (dest_len) { - /* Did we already process the terminating zero ? */ - if (dest[dest_len-1] != 0) { - size_t size = talloc_get_size(dest); - /* Have we got space to append the '\0' ? */ - if (size <= dest_len) { - /* No, realloc. */ - dest = TALLOC_REALLOC_ARRAY(ctx, dest, char, - dest_len+1); - if (!dest) { - /* talloc fail. */ - dest_len = (size_t)-1; - return NULL; - } - } - /* Yay - space ! */ - dest[dest_len] = '\0'; - dest_len++; - } - } else if (dest) { - dest[0] = 0; - } - - return dest; -} - /* Converts a string from internal samba format to unicode */ @@ -370,64 +312,6 @@ int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src) return -1; } -/******************************************************************* - Convert a (little-endian) UNISTR2 structure to an ASCII string. -********************************************************************/ - -void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) -{ - if ((str == NULL) || (str->uni_str_len == 0)) { - *dest='\0'; - return; - } - pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN); -} - -/******************************************************************* - Duplicate a UNISTR2 string into a null terminated char* - using a talloc context. -********************************************************************/ - -char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str) -{ - char *s = NULL; - - if (!str || !str->buffer) { - return NULL; - } - if (pull_ucs2_base_talloc(ctx, - NULL, - &s, - str->buffer, - str->uni_str_len*2, - STR_NOALIGN) == (size_t)-1) { - return NULL; - } - return s; -} - -/******************************************************************* - Return a string for displaying a UNISTR2. Guarentees to return a - valid string - "" if nothing else. - Changed to use talloc_tos() under the covers.... JRA. -********************************************************************/ - -const char *unistr2_static(const UNISTR2 *str) -{ - char *dest = NULL; - - if ((str == NULL) || (str->uni_str_len == 0)) { - return ""; - } - - dest = unistr2_to_ascii_talloc(talloc_tos(), str); - if (!dest) { - return ""; - } - - return dest; -} - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ -- cgit From 3277b19800c6c56a32b7641d293e496475d8c62a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 19 Mar 2009 19:18:14 +1100 Subject: s3:rpc_parse remove unused prs_unistr2() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 1 - source3/rpc_parse/parse_prs.c | 38 -------------------------------------- 2 files changed, 39 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index d5c11faf56..7ae008511c 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5782,7 +5782,6 @@ bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); bool prs_uint16uni(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len); -bool prs_unistr2(bool charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str); bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str); bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_buf_size); bool prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str); diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 94732b0a74..dfbd6dac74 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1048,44 +1048,6 @@ bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uin return True; } -/****************************************************************** - Stream a unicode string, length/buffer specified separately, - in uint16 chars. The unicode string is already in little-endian format. - ********************************************************************/ - -bool prs_unistr2(bool charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str) -{ - char *p; - char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16)); - if (q == NULL) - return False; - - /* If the string is empty, we don't have anything to stream */ - if (str->uni_str_len==0) - return True; - - if (UNMARSHALLING(ps)) { - if (str->uni_str_len > str->uni_max_len) { - return False; - } - if (str->uni_max_len) { - str->buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_max_len); - if (str->buffer == NULL) - return False; - } else { - str->buffer = NULL; - } - } - - p = (char *)str->buffer; - - dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len); - - ps->data_offset += (str->uni_str_len * sizeof(uint16)); - - return True; -} - /******************************************************************* Stream a unicode null-terminated string. As the string is already in little-endian format then do it as a stream of bytes. -- cgit From 0c22d55134b39a6bc983b4f852f623a51af4d362 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 19 Mar 2009 19:20:08 +1100 Subject: s3:charcnv Remove unused unistrcpy() and unistrlen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 2 -- source3/lib/util_unistr.c | 37 ------------------------------------- 2 files changed, 39 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 7ae008511c..f8a28ef165 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1595,8 +1595,6 @@ int strcmp_wa(const smb_ucs2_t *a, const char *b); int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len); smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p); smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins); -int unistrlen(uint16 *s); -int unistrcpy(uint16 *dst, uint16 *src); int toupper_ascii(int c); int tolower_ascii(int c); int isupper_ascii(int c); diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 3a6971dcce..7d80b3cdea 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -850,43 +850,6 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) return NULL; } -/******************************************************************* - Returns the length in number of wide characters. -******************************************************************/ - -int unistrlen(uint16 *s) -{ - int len; - - if (!s) { - return -1; - } - - for (len=0; SVAL(s,0); s++,len++) { - ; - } - - return len; -} - -/******************************************************************* - Strcpy for unicode strings. Returns length (in num of wide chars). - Not odd align safe. -********************************************************************/ - -int unistrcpy(uint16 *dst, uint16 *src) -{ - int num_wchars = 0; - - while (SVAL(src,0)) { - *dst++ = *src++; - num_wchars++; - } - *dst = 0; - - return num_wchars; -} - /************************************************************* ascii only toupper - saves the need for smbd to be in C locale. *************************************************************/ -- cgit From c5b24d65cdb1b32196681499dcaf23ea70e1019b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 2 Apr 2009 16:15:16 +0200 Subject: s3-spoolss: set servername to global_myname() in set_printer_hnd_name(). This allows spoolss_OpenPrinterEx to open a printer by printername. Now the Samba3 spoolss server passes the RPC-SPOOLSS-WIN test. Guenther --- source3/rpc_server/srv_spoolss_nt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 7bb0571042..098e59216b 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -445,7 +445,7 @@ static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename) aprinter++; } } else { - servername = ""; + servername = global_myname(); } /* save the servername to fill in replies on this handle */ -- cgit From 6859b805e84af91eca641ec1b91b844cbdab4065 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 18 Mar 2009 18:05:17 +1100 Subject: s3:lib Use push_ucs2_talloc() in ms_fnmatch() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/lib/ms_fnmatch.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index ca534467fa..1eac9fa14a 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -170,12 +170,12 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, } } - if (!push_ucs2_allocate(&p, pattern, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &p, pattern, &converted_size)) { return -1; } - if (!push_ucs2_allocate(&s, string, &converted_size)) { - SAFE_FREE(p); + if (!push_ucs2_talloc(talloc_tos(), &s, string, &converted_size)) { + TALLOC_FREE(p); return -1; } @@ -214,8 +214,8 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, else { max_n = SMB_CALLOC_ARRAY(struct max_n, count); if (!max_n) { - SAFE_FREE(p); - SAFE_FREE(s); + TALLOC_FREE(p); + TALLOC_FREE(s); return -1; } max_n_free = max_n; @@ -225,8 +225,8 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive); SAFE_FREE(max_n_free); - SAFE_FREE(p); - SAFE_FREE(s); + TALLOC_FREE(p); + TALLOC_FREE(s); return ret; } -- cgit From b36fab0491a7f73ac9dffea6397167c5bdd82a2a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 01:52:28 +0200 Subject: s3-svcctl: no need to define SVCCTL_NUM_INTERNAL_SERVICES twice in a file. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 848cdc25d0..6aafd5ab2c 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -32,8 +32,6 @@ struct service_control_op { SERVICE_CONTROL_OPS *ops; }; -#define SVCCTL_NUM_INTERNAL_SERVICES 4 - /* handle external services */ extern SERVICE_CONTROL_OPS rcinit_svc_ops; -- cgit From 8e3145e55194cfef56fa792edbed724ef4bf111a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 02:11:27 +0200 Subject: svcctl: use offered/needed for buffer sizes as in spoolss. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 6aafd5ab2c..ddfe0df10b 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -444,7 +444,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p, buffer_size += buffer_size % 4; - if (buffer_size > r->in.buf_size ) { + if (buffer_size > r->in.offered) { num_services = 0; result = WERR_MORE_DATA; } @@ -466,12 +466,12 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p, } blob = ndr_push_blob(ndr); - if (blob.length >= r->in.buf_size) { - memcpy(r->out.service, blob.data, r->in.buf_size); + if (blob.length >= r->in.offered) { + memcpy(r->out.service, blob.data, r->in.offered); } } - *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size; + *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; *r->out.services_returned = (uint32)num_services; *r->out.resume_handle = 0x0; @@ -552,7 +552,7 @@ WERROR _svcctl_EnumDependentServicesW(pipes_struct *p, incoming buffer size (even in the case of failure */ /* this is done in the autogenerated server already - gd */ - *r->out.bytes_needed = r->in.buf_size; + *r->out.needed = r->in.offered; /* no dependent services...basically a stub function */ *r->out.services_returned = 0; @@ -580,7 +580,7 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p, /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure) */ - *r->out.bytes_needed = r->in.buf_size; + *r->out.needed = r->in.offered; switch ( r->in.info_level ) { case SVC_STATUS_PROCESS_INFO: @@ -612,9 +612,9 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p, buffer_size += buffer_size % 4; - *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size; + *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; - if (buffer_size > r->in.buf_size ) { + if (buffer_size > r->in.offered ) { return WERR_INSUFFICIENT_BUFFER; } @@ -697,7 +697,7 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p, /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ - *r->out.bytes_needed = r->in.buf_size; + *r->out.needed = r->in.offered; wresult = fill_svc_config( p->mem_ctx, info->name, r->out.query, p->server_info->ptok); @@ -705,9 +705,9 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p, return wresult; buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0); - *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size; + *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; - if (buffer_size > r->in.buf_size ) { + if (buffer_size > r->in.offered ) { ZERO_STRUCTP(r->out.query); return WERR_INSUFFICIENT_BUFFER; } @@ -735,7 +735,7 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p, /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ - *r->out.bytes_needed = r->in.buf_size; + *r->out.needed = r->in.offered; switch ( r->in.info_level ) { case SERVICE_CONFIG_DESCRIPTION: @@ -792,9 +792,9 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p, } buffer_size += buffer_size % 4; - *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size; + *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; - if (buffer_size > r->in.buf_size ) + if (buffer_size > r->in.offered) return WERR_INSUFFICIENT_BUFFER; return WERR_OK; -- cgit From 403422e1ea8f654a9dee12566b8b28c09fe301c8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 03:00:16 +0200 Subject: s3-selftest: Samba3 passes RPC-SVCCTL so enable it during make test. Guenther --- source3/script/tests/test_posix_s3.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 0885b139bb..2832d1df30 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -40,6 +40,7 @@ raw="$raw RAW-SAMBA3ROOTDIRFID" rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC" rpc="$rpc RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC" rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME" +rpc="$rpc RPC-SVCCTL" # NOTE: to enable the UNIX-WHOAMI test, we need to change the default share # config to allow guest access. I'm not sure whether this would break other -- cgit From 78951bd7f4d8bfe13691b3291151c8dedd8e29ef Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 12:47:10 +0200 Subject: s3-util-sock: add ismyaddr() check in is_myname_or_ipaddr(). Guenther --- source3/lib/util_sock.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3') diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 21dd624b54..5f9d4768ba 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1942,6 +1942,10 @@ bool is_myname_or_ipaddr(const char *s) return false; } + if (ismyaddr((struct sockaddr *)&ss)) { + return true; + } + if (is_zero_addr((struct sockaddr *)&ss) || is_loopback_addr((struct sockaddr *)&ss)) { return false; -- cgit From fa7f2ffe5116dce69e89b990f816a32721474fb6 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 13:11:16 +0200 Subject: s3-selftest: add root for make test as well (not only make selftest). Guenther --- source3/script/tests/selftest.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index d49c5b0ca1..60b71a5adc 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -268,6 +268,7 @@ EOF ## cat >$NSS_WRAPPER_PASSWD< Date: Thu, 19 Mar 2009 23:38:00 +0100 Subject: s3-selftest: As Samba3 now passes RPC-SPOOLSS-WIN enable it against ourself. Guenther --- source3/script/tests/test_posix_s3.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 2832d1df30..18e8ef75af 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -40,7 +40,7 @@ raw="$raw RAW-SAMBA3ROOTDIRFID" rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC" rpc="$rpc RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC" rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME" -rpc="$rpc RPC-SVCCTL" +rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN" # NOTE: to enable the UNIX-WHOAMI test, we need to change the default share # config to allow guest access. I'm not sure whether this would break other -- cgit From 5654f141a2067692992d3a83aa3b16fa59b6bab9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 14:37:40 +0200 Subject: s3-rpc-server: remove unused rpc_server/srv_util.c file. Guenther --- source3/rpc_server/srv_util.c | 88 ------------------------------------------- 1 file changed, 88 deletions(-) delete mode 100644 source3/rpc_server/srv_util.c (limited to 'source3') diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c deleted file mode 100644 index b276e75faa..0000000000 --- a/source3/rpc_server/srv_util.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Paul Ashton 1997-1998, - * Copyright (C) Andrew Bartlett 2004. - * - * 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 - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -/* this module apparently provides an implementation of DCE/RPC over a - * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC - * documentation are available (in on-line form) from the X-Open group. - * - * this module should provide a level of abstraction between SMB - * and DCE/RPC, while minimising the amount of mallocs, unnecessary - * data copies, and network traffic. - * - * in this version, which takes a "let's learn what's going on and - * get something running" approach, there is additional network - * traffic generated, but the code should be easier to understand... - * - * ... if you read the docs. or stare at packets for weeks on end. - * - */ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -#if 0 /* these aren't used currently but are here if you need them */ - -typedef struct { - uint32 rid; - const char *name; -} rid_name; - -/* - * A list of the rids of well known BUILTIN and Domain users - * and groups. - */ - -static const rid_name builtin_alias_rids[] = -{ - { BUILTIN_ALIAS_RID_ADMINS , "Administrators" }, - { BUILTIN_ALIAS_RID_USERS , "Users" }, - { BUILTIN_ALIAS_RID_GUESTS , "Guests" }, - { BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" }, - - { BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" }, - { BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" }, - { BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" }, - { BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" }, - { BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" }, - { 0 , NULL } -}; - -/* array lookup of well-known Domain RID users. */ -static const rid_name domain_user_rids[] = -{ - { DOMAIN_USER_RID_ADMIN , "Administrator" }, - { DOMAIN_USER_RID_GUEST , "Guest" }, - { 0 , NULL } -}; - -/* array lookup of well-known Domain RID groups. */ -static const rid_name domain_group_rids[] = -{ - { DOMAIN_GROUP_RID_ADMINS , "Domain Admins" }, - { DOMAIN_GROUP_RID_USERS , "Domain Users" }, - { DOMAIN_GROUP_RID_GUESTS , "Domain Guests" }, - { 0 , NULL } -}; -#endif - -- cgit From 98d703a6b7c102db49b6cdc2a57545a90efefabf Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 14:29:04 +0200 Subject: s3-eventlog: move rpc_server/srv_eventlog_lib.c out of rpc_server. Guenther --- source3/Makefile.in | 2 +- source3/include/proto.h | 2 +- source3/lib/eventlog/eventlog.c | 960 ++++++++++++++++++++++++++++++++++ source3/rpc_server/srv_eventlog_lib.c | 960 ---------------------------------- 4 files changed, 962 insertions(+), 962 deletions(-) create mode 100644 source3/lib/eventlog/eventlog.c delete mode 100644 source3/rpc_server/srv_eventlog_lib.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 1578abf6b6..8b9bcbf9c6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -568,7 +568,7 @@ REG_FULL_OBJ = $(REG_SMBCONF_OBJ) \ registry/reg_perfcount.o \ registry/reg_util_legacy.o -LIB_EVENTLOG_OBJ = rpc_server/srv_eventlog_lib.o +LIB_EVENTLOG_OBJ = lib/eventlog/eventlog.o RPC_LSA_OBJ = rpc_server/srv_lsa_nt.o ../librpc/gen_ndr/srv_lsa.o diff --git a/source3/include/proto.h b/source3/include/proto.h index f8a28ef165..c8c2ece968 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5844,7 +5844,7 @@ bool smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len, RPC_AUTH_SCHANNEL_CHK * chk, prs_struct *ps, int depth); -/* The following definitions come from rpc_server/srv_eventlog_lib.c */ +/* The following definitions come from lib/eventlog/eventlog.c */ TDB_CONTEXT *elog_init_tdb( char *tdbfilename ); char *elog_tdbname(TALLOC_CTX *ctx, const char *name ); diff --git a/source3/lib/eventlog/eventlog.c b/source3/lib/eventlog/eventlog.c new file mode 100644 index 0000000000..f83c4fc3b8 --- /dev/null +++ b/source3/lib/eventlog/eventlog.c @@ -0,0 +1,960 @@ +/* + * Unix SMB/CIFS implementation. + * Eventlog utility routines + * Copyright (C) Marcin Krzysztof Porwit 2005, + * Copyright (C) Brian Moran 2005. + * Copyright (C) Gerald (Jerry) Carter 2005. + * Copyright (C) Guenther Deschner 2009. + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" + +/* maintain a list of open eventlog tdbs with reference counts */ + +static ELOG_TDB *open_elog_list; + +/******************************************************************** + Init an Eventlog TDB, and return it. If null, something bad + happened. +********************************************************************/ + +TDB_CONTEXT *elog_init_tdb( char *tdbfilename ) +{ + TDB_CONTEXT *tdb; + + DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n", + tdbfilename)); + + tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT, + O_RDWR|O_CREAT|O_TRUNC, 0660 ); + + if ( !tdb ) { + DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) ); + return NULL; + } + + /* initialize with defaults, copy real values in here from registry */ + + tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 ); + tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 ); + tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 ); + tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 ); + + tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 ); + + return tdb; +} + +/******************************************************************** + make the tdb file name for an event log, given destination buffer + and size. Caller must free memory. +********************************************************************/ + +char *elog_tdbname(TALLOC_CTX *ctx, const char *name ) +{ + char *path = talloc_asprintf(ctx, "%s/%s.tdb", + state_path("eventlog"), + name); + if (!path) { + return NULL; + } + strlower_m(path); + return path; +} + + +/******************************************************************** + this function is used to count up the number of bytes in a + particular TDB +********************************************************************/ + +struct trav_size_struct { + int size; + int rec_count; +}; + +static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, + void *state ) +{ + struct trav_size_struct *tsize = (struct trav_size_struct *)state; + + tsize->size += data.dsize; + tsize->rec_count++; + + return 0; +} + +/******************************************************************** + returns the size of the eventlog, and if MaxSize is a non-null + ptr, puts the MaxSize there. This is purely a way not to have yet + another function that solely reads the maxsize of the eventlog. + Yeah, that's it. +********************************************************************/ + +int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention ) +{ + struct trav_size_struct tsize; + + if ( !tdb ) + return 0; + + ZERO_STRUCT( tsize ); + + tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize ); + + if ( MaxSize != NULL ) { + *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE ); + } + + if ( Retention != NULL ) { + *Retention = tdb_fetch_int32( tdb, EVT_RETENTION ); + } + + DEBUG( 1, + ( "eventlog size: [%d] for [%d] records\n", tsize.size, + tsize.rec_count ) ); + return tsize.size; +} + +/******************************************************************** + Discard early event logs until we have enough for 'needed' bytes... + NO checking done beforehand to see that we actually need to do + this, and it's going to pluck records one-by-one. So, it's best + to determine that this needs to be done before doing it. + + Setting whack_by_date to True indicates that eventlogs falling + outside of the retention range need to go... + + return True if we made enough room to accommodate needed bytes +********************************************************************/ + +static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed, + bool whack_by_date ) +{ + int32_t start_record, i, new_start; + int32_t end_record; + int32_t reclen, tresv1, trecnum, timegen, timewr; + int nbytes, len, Retention, MaxSize; + TDB_DATA key, ret; + time_t current_time, exp_time; + + /* discard some eventlogs */ + + /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos, + although records not necessarily guaranteed to have successive times */ + /* */ + + /* lock */ + tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 ); + /* read */ + end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); + start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY ); + Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION ); + MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE ); + + time( ¤t_time ); + + /* calculate ... */ + exp_time = current_time - Retention; /* discard older than exp_time */ + + /* todo - check for sanity in next_record */ + nbytes = 0; + + DEBUG( 3, + ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n", + MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) ); + DEBUG( 3, + ( "Start Record [%u] End Record [%u]\n", + (unsigned int)start_record, + (unsigned int)end_record )); + + for ( i = start_record; i < end_record; i++ ) { + /* read a record, add the amt to nbytes */ + key.dsize = sizeof(int32_t); + key.dptr = (unsigned char *)&i; + ret = tdb_fetch( the_tdb, key ); + if ( ret.dsize == 0 ) { + DEBUG( 8, + ( "Can't find a record for the key, record [%d]\n", + i ) ); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); + return False; + } + nbytes += ret.dsize; /* note this includes overhead */ + + len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen, + &tresv1, &trecnum, &timegen, &timewr ); + if (len == -1) { + DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n")); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); + SAFE_FREE( ret.dptr ); + return False; + } + + DEBUG( 8, + ( "read record %u, record size is [%d], total so far [%d]\n", + (unsigned int)i, reclen, nbytes ) ); + + SAFE_FREE( ret.dptr ); + + /* note that other servers may just stop writing records when the size limit + is reached, and there are no records older than 'retention'. This doesn't + like a very useful thing to do, so instead we whack (as in sleeps with the + fishes) just enough records to fit the what we need. This behavior could + be changed to 'match', if the need arises. */ + + if ( !whack_by_date && ( nbytes >= needed ) ) + break; /* done */ + if ( whack_by_date && ( timegen >= exp_time ) ) + break; /* done */ + } + + DEBUG( 3, + ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n", + nbytes, needed, (unsigned int)start_record, (unsigned int)i ) ); + /* todo - remove eventlog entries here and set starting record to start_record... */ + new_start = i; + if ( start_record != new_start ) { + for ( i = start_record; i < new_start; i++ ) { + key.dsize = sizeof(int32_t); + key.dptr = (unsigned char *)&i; + tdb_delete( the_tdb, key ); + } + + tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start ); + } + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); + return True; +} + +/******************************************************************** + some hygiene for an eventlog - see how big it is, and then + calculate how many bytes we need to remove +********************************************************************/ + +bool prune_eventlog( TDB_CONTEXT * tdb ) +{ + int MaxSize, Retention, CalcdSize; + + if ( !tdb ) { + DEBUG( 4, ( "No eventlog tdb handle\n" ) ); + return False; + } + + CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention ); + DEBUG( 3, + ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize, + MaxSize ) ); + + if ( CalcdSize > MaxSize ) { + return make_way_for_eventlogs( tdb, CalcdSize - MaxSize, + False ); + } + + return make_way_for_eventlogs( tdb, 0, True ); +} + +/******************************************************************** +********************************************************************/ + +static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) +{ + int calcd_size; + int MaxSize, Retention; + + /* see if we can write to the eventlog -- do a policy enforcement */ + if ( !tdb ) + return False; /* tdb is null, so we can't write to it */ + + + if ( needed < 0 ) + return False; + MaxSize = 0; + Retention = 0; + + calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention ); + + if ( calcd_size <= MaxSize ) + return True; /* you betcha */ + if ( calcd_size + needed < MaxSize ) + return True; + + if ( Retention == 0xffffffff ) { + return False; /* see msdn - we can't write no room, discard */ + } + /* + note don't have to test, but always good to show intent, in case changes needed + later + */ + + if ( Retention == 0x00000000 ) { + /* discard record(s) */ + /* todo - decide when to remove a bunch vs. just what we need... */ + return make_way_for_eventlogs( tdb, calcd_size - MaxSize, + True ); + } + + return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False ); +} + +/******************************************************************* +*******************************************************************/ + +ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only ) +{ + TDB_CONTEXT *tdb = NULL; + uint32_t vers_id; + ELOG_TDB *ptr; + char *tdbpath = NULL; + ELOG_TDB *tdb_node = NULL; + char *eventlogdir; + TALLOC_CTX *ctx = talloc_tos(); + + /* check for invalid options */ + + if (force_clear && read_only) { + DEBUG(1,("elog_open_tdb: Invalid flags\n")); + return NULL; + } + + /* first see if we have an open context */ + + for ( ptr=open_elog_list; ptr; ptr=ptr->next ) { + if ( strequal( ptr->name, logname ) ) { + ptr->ref_count++; + + /* trick to alow clearing of the eventlog tdb. + The force_clear flag should imply that someone + has done a force close. So make sure the tdb + is NULL. If this is a normal open, then just + return the existing reference */ + + if ( force_clear ) { + SMB_ASSERT( ptr->tdb == NULL ); + break; + } + else + return ptr; + } + } + + /* make sure that the eventlog dir exists */ + + eventlogdir = state_path( "eventlog" ); + if ( !directory_exist( eventlogdir ) ) + mkdir( eventlogdir, 0755 ); + + /* get the path on disk */ + + tdbpath = elog_tdbname(ctx, logname); + if (!tdbpath) { + return NULL; + } + + DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n", + tdbpath, force_clear?"True":"False" )); + + /* the tdb wasn't already open or this is a forced clear open */ + + if ( !force_clear ) { + + tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 ); + if ( tdb ) { + vers_id = tdb_fetch_int32( tdb, EVT_VERSION ); + + if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) { + DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n", + vers_id, tdbpath)); + tdb_close( tdb ); + tdb = elog_init_tdb( tdbpath ); + } + } + } + + if ( !tdb ) + tdb = elog_init_tdb( tdbpath ); + + /* if we got a valid context, then add it to the list */ + + if ( tdb ) { + /* on a forced clear, just reset the tdb context if we already + have an open entry in the list */ + + if ( ptr ) { + ptr->tdb = tdb; + return ptr; + } + + if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) { + DEBUG(0,("elog_open_tdb: talloc() failure!\n")); + tdb_close( tdb ); + return NULL; + } + + tdb_node->name = talloc_strdup( tdb_node, logname ); + tdb_node->tdb = tdb; + tdb_node->ref_count = 1; + + DLIST_ADD( open_elog_list, tdb_node ); + } + + return tdb_node; +} + +/******************************************************************* + Wrapper to handle reference counts to the tdb +*******************************************************************/ + +int elog_close_tdb( ELOG_TDB *etdb, bool force_close ) +{ + TDB_CONTEXT *tdb; + + if ( !etdb ) + return 0; + + etdb->ref_count--; + + SMB_ASSERT( etdb->ref_count >= 0 ); + + if ( etdb->ref_count == 0 ) { + tdb = etdb->tdb; + DLIST_REMOVE( open_elog_list, etdb ); + TALLOC_FREE( etdb ); + return tdb_close( tdb ); + } + + if ( force_close ) { + tdb = etdb->tdb; + etdb->tdb = NULL; + return tdb_close( tdb ); + } + + return 0; +} + +/******************************************************************** + Note that it's a pretty good idea to initialize the Eventlog_entry + structure to zero's before calling parse_logentry on an batch of + lines that may resolve to a record. ALSO, it's a good idea to + remove any linefeeds (that's EOL to you and me) on the lines + going in. +********************************************************************/ + +bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor ) +{ + char *start = NULL, *stop = NULL; + + start = line; + + /* empty line signyfiying record delimeter, or we're at the end of the buffer */ + if ( start == NULL || strlen( start ) == 0 ) { + DEBUG( 6, + ( "parse_logentry: found end-of-record indicator.\n" ) ); + *eor = True; + return True; + } + if ( !( stop = strchr( line, ':' ) ) ) { + return False; + } + + DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) ); + + if ( 0 == strncmp( start, "LEN", stop - start ) ) { + /* This will get recomputed later anyway -- probably not necessary */ + entry->size = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "RS1", stop - start ) ) { + /* For now all these reserved entries seem to have the same value, + which can be hardcoded to int(1699505740) for now */ + entry->reserved = talloc_strdup(mem_ctx, "eLfL"); + } else if ( 0 == strncmp( start, "RCN", stop - start ) ) { + entry->record_number = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "TMG", stop - start ) ) { + entry->time_generated = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "TMW", stop - start ) ) { + entry->time_written = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "EID", stop - start ) ) { + entry->event_id = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "ETP", stop - start ) ) { + if ( strstr( start, "ERROR" ) ) { + entry->event_type = EVENTLOG_ERROR_TYPE; + } else if ( strstr( start, "WARNING" ) ) { + entry->event_type = EVENTLOG_WARNING_TYPE; + } else if ( strstr( start, "INFO" ) ) { + entry->event_type = EVENTLOG_INFORMATION_TYPE; + } else if ( strstr( start, "AUDIT_SUCCESS" ) ) { + entry->event_type = EVENTLOG_AUDIT_SUCCESS; + } else if ( strstr( start, "AUDIT_FAILURE" ) ) { + entry->event_type = EVENTLOG_AUDIT_FAILURE; + } else if ( strstr( start, "SUCCESS" ) ) { + entry->event_type = EVENTLOG_SUCCESS; + } else { + /* some other eventlog type -- currently not defined in MSDN docs, so error out */ + return False; + } + } + +/* + else if(0 == strncmp(start, "NST", stop - start)) + { + entry->num_of_strings = atoi(stop + 1); + } +*/ + else if ( 0 == strncmp( start, "ECT", stop - start ) ) { + entry->event_category = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "RS2", stop - start ) ) { + entry->reserved_flags = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "CRN", stop - start ) ) { + entry->closing_record_number = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "USL", stop - start ) ) { + entry->sid_length = atoi( stop + 1 ); + } else if ( 0 == strncmp( start, "SRC", stop - start ) ) { + stop++; + while ( isspace( stop[0] ) ) { + stop++; + } + entry->source_name_len = strlen_m_term(stop); + entry->source_name = talloc_strdup(mem_ctx, stop); + if (entry->source_name_len == (uint32_t)-1 || + entry->source_name == NULL) { + return false; + } + } else if ( 0 == strncmp( start, "SRN", stop - start ) ) { + stop++; + while ( isspace( stop[0] ) ) { + stop++; + } + entry->computer_name_len = strlen_m_term(stop); + entry->computer_name = talloc_strdup(mem_ctx, stop); + if (entry->computer_name_len == (uint32_t)-1 || + entry->computer_name == NULL) { + return false; + } + } else if ( 0 == strncmp( start, "SID", stop - start ) ) { + smb_ucs2_t *dummy = NULL; + stop++; + while ( isspace( stop[0] ) ) { + stop++; + } + entry->sid_length = rpcstr_push_talloc(mem_ctx, + &dummy, + stop); + if (entry->sid_length == (uint32_t)-1) { + return false; + } + entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length); + if (entry->sid.data == NULL) { + return false; + } + } else if ( 0 == strncmp( start, "STR", stop - start ) ) { + size_t tmp_len; + int num_of_strings; + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while ( isspace(stop[0])) { + stop++; + } + tmp_len = strlen_m_term(stop); + if (tmp_len == (size_t)-1) { + return false; + } + num_of_strings = entry->num_of_strings; + if (!add_string_to_array(mem_ctx, stop, &entry->strings, + &num_of_strings)) { + return false; + } + if (num_of_strings > 0xffff) { + return false; + } + entry->num_of_strings = num_of_strings; + entry->strings_len += tmp_len; + } else if ( 0 == strncmp( start, "DAT", stop - start ) ) { + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while ( isspace( stop[0] ) ) { + stop++; + } + entry->data_length = strlen_m(stop); + entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length); + if (!entry->data.data) { + return false; + } + } else { + /* some other eventlog entry -- not implemented, so dropping on the floor */ + DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) ); + /* For now return true so that we can keep on parsing this mess. Eventually + we will return False here. */ + return true; + } + return true; +} + +/******************************************************************* + calculate the correct fields etc for an eventlog entry +*******************************************************************/ + +size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r) +{ + size_t size = 56; /* static size of integers before buffers start */ + + r->source_name_len = strlen_m_term(r->source_name) * 2; + r->computer_name_len = strlen_m_term(r->computer_name) * 2; + r->strings_len = ndr_size_string_array(r->strings, + r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2; + + /* fix up the eventlog entry structure as necessary */ + r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 ); + r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4; + + if (r->sid_length == 0) { + /* Should not pad to a DWORD boundary for writing out the sid if there is + no SID, so just propagate the padding to pad the data */ + r->padding += r->sid_padding; + r->sid_padding = 0; + } + + size += r->source_name_len; + size += r->computer_name_len; + size += r->sid_padding; + size += r->sid_length; + size += r->strings_len; + size += r->data_length; + size += r->padding; + /* need another copy of length at the end of the data */ + size += sizeof(r->size); + + r->size = size; + + return size; +} + + +/******************************************************************** + ********************************************************************/ + +struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number) +{ + struct eventlog_Record_tdb *r; + TDB_DATA data, key; + + int32_t srecno; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + srecno = record_number; + key.dptr = (unsigned char *)&srecno; + key.dsize = sizeof(int32_t); + + data = tdb_fetch(tdb, key); + if (data.dsize == 0) { + DEBUG(8,("evlog_pull_record_tdb: " + "Can't find a record for the key, record %d\n", + record_number)); + return NULL; + } + + r = talloc_zero(mem_ctx, struct eventlog_Record_tdb); + if (!r) { + goto done; + } + + blob = data_blob_const(data.dptr, data.dsize); + + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r, + (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n", + record_number)); + TALLOC_FREE(r); + goto done; + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(eventlog_Record_tdb, r); + } + + DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n", + record_number)); + done: + SAFE_FREE(data.dptr); + + return r; +} + +/******************************************************************** + ********************************************************************/ + +struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number) +{ + struct eventlog_Record_tdb *t; + struct EVENTLOGRECORD *r; + NTSTATUS status; + + r = talloc_zero(mem_ctx, struct EVENTLOGRECORD); + if (!r) { + return NULL; + } + + t = evlog_pull_record_tdb(r, tdb, record_number); + if (!t) { + talloc_free(r); + return NULL; + } + + status = evlog_tdb_entry_to_evt_entry(r, t, r); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(r); + return NULL; + } + + r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, NULL, 0); + + return r; +} + +/******************************************************************** + write an eventlog entry. Note that we have to lock, read next + eventlog, increment, write, write the record, unlock + + coming into this, ee has the eventlog record, and the auxilliary date + (computer name, etc.) filled into the other structure. Before packing + into a record, this routine will calc the appropriate padding, etc., + and then blast out the record in a form that can be read back in + ********************************************************************/ + +NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct eventlog_Record_tdb *r, + uint32_t *record_number) +{ + TDB_DATA kbuf, ebuf; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + int ret; + + if (!r) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!can_write_to_eventlog(tdb, r->size)) { + return NT_STATUS_EVENTLOG_CANT_START; + } + + /* need to read the record number and insert it into the entry here */ + + /* lock */ + ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1); + if (ret == -1) { + return NT_STATUS_LOCK_NOT_GRANTED; + } + + /* read */ + r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD); + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r, + (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return ndr_map_error2ntstatus(ndr_err); + } + + /* increment the record count */ + + kbuf.dsize = sizeof(int32_t); + kbuf.dptr = (uint8_t *)&r->record_number; + + ebuf.dsize = blob.length; + ebuf.dptr = blob.data; + + ret = tdb_store(tdb, kbuf, ebuf, 0); + if (ret == -1) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return NT_STATUS_EVENTLOG_FILE_CORRUPT; + } + + ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1); + if (ret == -1) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return NT_STATUS_EVENTLOG_FILE_CORRUPT; + } + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + + if (record_number) { + *record_number = r->record_number; + } + + return NT_STATUS_OK; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct EVENTLOGRECORD *r, + uint32_t *record_number) +{ + struct eventlog_Record_tdb *t; + NTSTATUS status; + + t = talloc_zero(mem_ctx, struct eventlog_Record_tdb); + if (!t) { + return NT_STATUS_NO_MEMORY; + } + + status = evlog_evt_entry_to_tdb_entry(t, r, t); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(t); + return status; + } + + status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number); + talloc_free(t); + + return status; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx, + const struct EVENTLOGRECORD *e, + struct eventlog_Record_tdb *t) +{ + uint32_t i; + + ZERO_STRUCTP(t); + + t->size = e->Length; + t->reserved = e->Reserved; + t->record_number = e->RecordNumber; + t->time_generated = e->TimeGenerated; + t->time_written = e->TimeWritten; + t->event_id = e->EventID; + t->event_type = e->EventType; + t->num_of_strings = e->NumStrings; + t->event_category = e->EventCategory; + t->reserved_flags = e->ReservedFlags; + t->closing_record_number = e->ClosingRecordNumber; + + t->stringoffset = e->StringOffset; + t->sid_length = e->UserSidLength; + t->sid_offset = e->UserSidOffset; + t->data_length = e->DataLength; + t->data_offset = e->DataOffset; + + t->source_name_len = 2 * strlen_m_term(e->SourceName); + t->source_name = talloc_strdup(mem_ctx, e->SourceName); + NT_STATUS_HAVE_NO_MEMORY(t->source_name); + + t->computer_name_len = 2 * strlen_m_term(e->Computername); + t->computer_name = talloc_strdup(mem_ctx, e->Computername); + NT_STATUS_HAVE_NO_MEMORY(t->computer_name); + + /* t->sid_padding; */ + if (e->UserSidLength > 0) { + const char *sid_str = NULL; + smb_ucs2_t *dummy = NULL; + sid_str = sid_string_talloc(mem_ctx, &e->UserSid); + t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str); + if (t->sid_length == -1) { + return NT_STATUS_NO_MEMORY; + } + t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length); + NT_STATUS_HAVE_NO_MEMORY(t->sid.data); + } + + t->strings = talloc_array(mem_ctx, const char *, e->NumStrings); + for (i=0; i < e->NumStrings; i++) { + t->strings[i] = talloc_strdup(t->strings, e->Strings[i]); + NT_STATUS_HAVE_NO_MEMORY(t->strings[i]); + } + + t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM); + t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength); + /* t->padding = r->Pad; */ + + return NT_STATUS_OK; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, + const struct eventlog_Record_tdb *t, + struct EVENTLOGRECORD *e) +{ + uint32_t i; + + ZERO_STRUCTP(e); + + e->Length = t->size; + e->Reserved = t->reserved; + e->RecordNumber = t->record_number; + e->TimeGenerated = t->time_generated; + e->TimeWritten = t->time_written; + e->EventID = t->event_id; + e->EventType = t->event_type; + e->NumStrings = t->num_of_strings; + e->EventCategory = t->event_category; + e->ReservedFlags = t->reserved_flags; + e->ClosingRecordNumber = t->closing_record_number; + + e->StringOffset = t->stringoffset; + e->UserSidLength = t->sid_length; + e->UserSidOffset = t->sid_offset; + e->DataLength = t->data_length; + e->DataOffset = t->data_offset; + + e->SourceName = talloc_strdup(mem_ctx, t->source_name); + NT_STATUS_HAVE_NO_MEMORY(e->SourceName); + + e->Computername = talloc_strdup(mem_ctx, t->computer_name); + NT_STATUS_HAVE_NO_MEMORY(e->Computername); + + if (t->sid_length > 0) { + const char *sid_str = NULL; + size_t len; + if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, + t->sid.data, t->sid.length, + (void **)&sid_str, &len, false)) { + return NT_STATUS_INVALID_SID; + } + if (len > 0) { + e->UserSid = *string_sid_talloc(mem_ctx, sid_str); + } + } + + e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings); + for (i=0; i < t->num_of_strings; i++) { + e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]); + NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]); + } + + e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length); + e->Pad = talloc_strdup(mem_ctx, ""); + NT_STATUS_HAVE_NO_MEMORY(e->Pad); + + e->Length2 = t->size; + + return NT_STATUS_OK; +} diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c deleted file mode 100644 index f83c4fc3b8..0000000000 --- a/source3/rpc_server/srv_eventlog_lib.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * Eventlog utility routines - * Copyright (C) Marcin Krzysztof Porwit 2005, - * Copyright (C) Brian Moran 2005. - * Copyright (C) Gerald (Jerry) Carter 2005. - * Copyright (C) Guenther Deschner 2009. - * - * 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 - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "includes.h" - -/* maintain a list of open eventlog tdbs with reference counts */ - -static ELOG_TDB *open_elog_list; - -/******************************************************************** - Init an Eventlog TDB, and return it. If null, something bad - happened. -********************************************************************/ - -TDB_CONTEXT *elog_init_tdb( char *tdbfilename ) -{ - TDB_CONTEXT *tdb; - - DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n", - tdbfilename)); - - tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT, - O_RDWR|O_CREAT|O_TRUNC, 0660 ); - - if ( !tdb ) { - DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) ); - return NULL; - } - - /* initialize with defaults, copy real values in here from registry */ - - tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 ); - tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 ); - tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 ); - tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 ); - - tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 ); - - return tdb; -} - -/******************************************************************** - make the tdb file name for an event log, given destination buffer - and size. Caller must free memory. -********************************************************************/ - -char *elog_tdbname(TALLOC_CTX *ctx, const char *name ) -{ - char *path = talloc_asprintf(ctx, "%s/%s.tdb", - state_path("eventlog"), - name); - if (!path) { - return NULL; - } - strlower_m(path); - return path; -} - - -/******************************************************************** - this function is used to count up the number of bytes in a - particular TDB -********************************************************************/ - -struct trav_size_struct { - int size; - int rec_count; -}; - -static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, - void *state ) -{ - struct trav_size_struct *tsize = (struct trav_size_struct *)state; - - tsize->size += data.dsize; - tsize->rec_count++; - - return 0; -} - -/******************************************************************** - returns the size of the eventlog, and if MaxSize is a non-null - ptr, puts the MaxSize there. This is purely a way not to have yet - another function that solely reads the maxsize of the eventlog. - Yeah, that's it. -********************************************************************/ - -int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention ) -{ - struct trav_size_struct tsize; - - if ( !tdb ) - return 0; - - ZERO_STRUCT( tsize ); - - tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize ); - - if ( MaxSize != NULL ) { - *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE ); - } - - if ( Retention != NULL ) { - *Retention = tdb_fetch_int32( tdb, EVT_RETENTION ); - } - - DEBUG( 1, - ( "eventlog size: [%d] for [%d] records\n", tsize.size, - tsize.rec_count ) ); - return tsize.size; -} - -/******************************************************************** - Discard early event logs until we have enough for 'needed' bytes... - NO checking done beforehand to see that we actually need to do - this, and it's going to pluck records one-by-one. So, it's best - to determine that this needs to be done before doing it. - - Setting whack_by_date to True indicates that eventlogs falling - outside of the retention range need to go... - - return True if we made enough room to accommodate needed bytes -********************************************************************/ - -static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed, - bool whack_by_date ) -{ - int32_t start_record, i, new_start; - int32_t end_record; - int32_t reclen, tresv1, trecnum, timegen, timewr; - int nbytes, len, Retention, MaxSize; - TDB_DATA key, ret; - time_t current_time, exp_time; - - /* discard some eventlogs */ - - /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos, - although records not necessarily guaranteed to have successive times */ - /* */ - - /* lock */ - tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 ); - /* read */ - end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); - start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY ); - Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION ); - MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE ); - - time( ¤t_time ); - - /* calculate ... */ - exp_time = current_time - Retention; /* discard older than exp_time */ - - /* todo - check for sanity in next_record */ - nbytes = 0; - - DEBUG( 3, - ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n", - MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) ); - DEBUG( 3, - ( "Start Record [%u] End Record [%u]\n", - (unsigned int)start_record, - (unsigned int)end_record )); - - for ( i = start_record; i < end_record; i++ ) { - /* read a record, add the amt to nbytes */ - key.dsize = sizeof(int32_t); - key.dptr = (unsigned char *)&i; - ret = tdb_fetch( the_tdb, key ); - if ( ret.dsize == 0 ) { - DEBUG( 8, - ( "Can't find a record for the key, record [%d]\n", - i ) ); - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - return False; - } - nbytes += ret.dsize; /* note this includes overhead */ - - len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen, - &tresv1, &trecnum, &timegen, &timewr ); - if (len == -1) { - DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n")); - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - SAFE_FREE( ret.dptr ); - return False; - } - - DEBUG( 8, - ( "read record %u, record size is [%d], total so far [%d]\n", - (unsigned int)i, reclen, nbytes ) ); - - SAFE_FREE( ret.dptr ); - - /* note that other servers may just stop writing records when the size limit - is reached, and there are no records older than 'retention'. This doesn't - like a very useful thing to do, so instead we whack (as in sleeps with the - fishes) just enough records to fit the what we need. This behavior could - be changed to 'match', if the need arises. */ - - if ( !whack_by_date && ( nbytes >= needed ) ) - break; /* done */ - if ( whack_by_date && ( timegen >= exp_time ) ) - break; /* done */ - } - - DEBUG( 3, - ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n", - nbytes, needed, (unsigned int)start_record, (unsigned int)i ) ); - /* todo - remove eventlog entries here and set starting record to start_record... */ - new_start = i; - if ( start_record != new_start ) { - for ( i = start_record; i < new_start; i++ ) { - key.dsize = sizeof(int32_t); - key.dptr = (unsigned char *)&i; - tdb_delete( the_tdb, key ); - } - - tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start ); - } - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - return True; -} - -/******************************************************************** - some hygiene for an eventlog - see how big it is, and then - calculate how many bytes we need to remove -********************************************************************/ - -bool prune_eventlog( TDB_CONTEXT * tdb ) -{ - int MaxSize, Retention, CalcdSize; - - if ( !tdb ) { - DEBUG( 4, ( "No eventlog tdb handle\n" ) ); - return False; - } - - CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention ); - DEBUG( 3, - ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize, - MaxSize ) ); - - if ( CalcdSize > MaxSize ) { - return make_way_for_eventlogs( tdb, CalcdSize - MaxSize, - False ); - } - - return make_way_for_eventlogs( tdb, 0, True ); -} - -/******************************************************************** -********************************************************************/ - -static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) -{ - int calcd_size; - int MaxSize, Retention; - - /* see if we can write to the eventlog -- do a policy enforcement */ - if ( !tdb ) - return False; /* tdb is null, so we can't write to it */ - - - if ( needed < 0 ) - return False; - MaxSize = 0; - Retention = 0; - - calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention ); - - if ( calcd_size <= MaxSize ) - return True; /* you betcha */ - if ( calcd_size + needed < MaxSize ) - return True; - - if ( Retention == 0xffffffff ) { - return False; /* see msdn - we can't write no room, discard */ - } - /* - note don't have to test, but always good to show intent, in case changes needed - later - */ - - if ( Retention == 0x00000000 ) { - /* discard record(s) */ - /* todo - decide when to remove a bunch vs. just what we need... */ - return make_way_for_eventlogs( tdb, calcd_size - MaxSize, - True ); - } - - return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False ); -} - -/******************************************************************* -*******************************************************************/ - -ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only ) -{ - TDB_CONTEXT *tdb = NULL; - uint32_t vers_id; - ELOG_TDB *ptr; - char *tdbpath = NULL; - ELOG_TDB *tdb_node = NULL; - char *eventlogdir; - TALLOC_CTX *ctx = talloc_tos(); - - /* check for invalid options */ - - if (force_clear && read_only) { - DEBUG(1,("elog_open_tdb: Invalid flags\n")); - return NULL; - } - - /* first see if we have an open context */ - - for ( ptr=open_elog_list; ptr; ptr=ptr->next ) { - if ( strequal( ptr->name, logname ) ) { - ptr->ref_count++; - - /* trick to alow clearing of the eventlog tdb. - The force_clear flag should imply that someone - has done a force close. So make sure the tdb - is NULL. If this is a normal open, then just - return the existing reference */ - - if ( force_clear ) { - SMB_ASSERT( ptr->tdb == NULL ); - break; - } - else - return ptr; - } - } - - /* make sure that the eventlog dir exists */ - - eventlogdir = state_path( "eventlog" ); - if ( !directory_exist( eventlogdir ) ) - mkdir( eventlogdir, 0755 ); - - /* get the path on disk */ - - tdbpath = elog_tdbname(ctx, logname); - if (!tdbpath) { - return NULL; - } - - DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n", - tdbpath, force_clear?"True":"False" )); - - /* the tdb wasn't already open or this is a forced clear open */ - - if ( !force_clear ) { - - tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 ); - if ( tdb ) { - vers_id = tdb_fetch_int32( tdb, EVT_VERSION ); - - if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) { - DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n", - vers_id, tdbpath)); - tdb_close( tdb ); - tdb = elog_init_tdb( tdbpath ); - } - } - } - - if ( !tdb ) - tdb = elog_init_tdb( tdbpath ); - - /* if we got a valid context, then add it to the list */ - - if ( tdb ) { - /* on a forced clear, just reset the tdb context if we already - have an open entry in the list */ - - if ( ptr ) { - ptr->tdb = tdb; - return ptr; - } - - if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) { - DEBUG(0,("elog_open_tdb: talloc() failure!\n")); - tdb_close( tdb ); - return NULL; - } - - tdb_node->name = talloc_strdup( tdb_node, logname ); - tdb_node->tdb = tdb; - tdb_node->ref_count = 1; - - DLIST_ADD( open_elog_list, tdb_node ); - } - - return tdb_node; -} - -/******************************************************************* - Wrapper to handle reference counts to the tdb -*******************************************************************/ - -int elog_close_tdb( ELOG_TDB *etdb, bool force_close ) -{ - TDB_CONTEXT *tdb; - - if ( !etdb ) - return 0; - - etdb->ref_count--; - - SMB_ASSERT( etdb->ref_count >= 0 ); - - if ( etdb->ref_count == 0 ) { - tdb = etdb->tdb; - DLIST_REMOVE( open_elog_list, etdb ); - TALLOC_FREE( etdb ); - return tdb_close( tdb ); - } - - if ( force_close ) { - tdb = etdb->tdb; - etdb->tdb = NULL; - return tdb_close( tdb ); - } - - return 0; -} - -/******************************************************************** - Note that it's a pretty good idea to initialize the Eventlog_entry - structure to zero's before calling parse_logentry on an batch of - lines that may resolve to a record. ALSO, it's a good idea to - remove any linefeeds (that's EOL to you and me) on the lines - going in. -********************************************************************/ - -bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor ) -{ - char *start = NULL, *stop = NULL; - - start = line; - - /* empty line signyfiying record delimeter, or we're at the end of the buffer */ - if ( start == NULL || strlen( start ) == 0 ) { - DEBUG( 6, - ( "parse_logentry: found end-of-record indicator.\n" ) ); - *eor = True; - return True; - } - if ( !( stop = strchr( line, ':' ) ) ) { - return False; - } - - DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) ); - - if ( 0 == strncmp( start, "LEN", stop - start ) ) { - /* This will get recomputed later anyway -- probably not necessary */ - entry->size = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "RS1", stop - start ) ) { - /* For now all these reserved entries seem to have the same value, - which can be hardcoded to int(1699505740) for now */ - entry->reserved = talloc_strdup(mem_ctx, "eLfL"); - } else if ( 0 == strncmp( start, "RCN", stop - start ) ) { - entry->record_number = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "TMG", stop - start ) ) { - entry->time_generated = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "TMW", stop - start ) ) { - entry->time_written = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "EID", stop - start ) ) { - entry->event_id = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "ETP", stop - start ) ) { - if ( strstr( start, "ERROR" ) ) { - entry->event_type = EVENTLOG_ERROR_TYPE; - } else if ( strstr( start, "WARNING" ) ) { - entry->event_type = EVENTLOG_WARNING_TYPE; - } else if ( strstr( start, "INFO" ) ) { - entry->event_type = EVENTLOG_INFORMATION_TYPE; - } else if ( strstr( start, "AUDIT_SUCCESS" ) ) { - entry->event_type = EVENTLOG_AUDIT_SUCCESS; - } else if ( strstr( start, "AUDIT_FAILURE" ) ) { - entry->event_type = EVENTLOG_AUDIT_FAILURE; - } else if ( strstr( start, "SUCCESS" ) ) { - entry->event_type = EVENTLOG_SUCCESS; - } else { - /* some other eventlog type -- currently not defined in MSDN docs, so error out */ - return False; - } - } - -/* - else if(0 == strncmp(start, "NST", stop - start)) - { - entry->num_of_strings = atoi(stop + 1); - } -*/ - else if ( 0 == strncmp( start, "ECT", stop - start ) ) { - entry->event_category = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "RS2", stop - start ) ) { - entry->reserved_flags = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "CRN", stop - start ) ) { - entry->closing_record_number = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "USL", stop - start ) ) { - entry->sid_length = atoi( stop + 1 ); - } else if ( 0 == strncmp( start, "SRC", stop - start ) ) { - stop++; - while ( isspace( stop[0] ) ) { - stop++; - } - entry->source_name_len = strlen_m_term(stop); - entry->source_name = talloc_strdup(mem_ctx, stop); - if (entry->source_name_len == (uint32_t)-1 || - entry->source_name == NULL) { - return false; - } - } else if ( 0 == strncmp( start, "SRN", stop - start ) ) { - stop++; - while ( isspace( stop[0] ) ) { - stop++; - } - entry->computer_name_len = strlen_m_term(stop); - entry->computer_name = talloc_strdup(mem_ctx, stop); - if (entry->computer_name_len == (uint32_t)-1 || - entry->computer_name == NULL) { - return false; - } - } else if ( 0 == strncmp( start, "SID", stop - start ) ) { - smb_ucs2_t *dummy = NULL; - stop++; - while ( isspace( stop[0] ) ) { - stop++; - } - entry->sid_length = rpcstr_push_talloc(mem_ctx, - &dummy, - stop); - if (entry->sid_length == (uint32_t)-1) { - return false; - } - entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length); - if (entry->sid.data == NULL) { - return false; - } - } else if ( 0 == strncmp( start, "STR", stop - start ) ) { - size_t tmp_len; - int num_of_strings; - /* skip past initial ":" */ - stop++; - /* now skip any other leading whitespace */ - while ( isspace(stop[0])) { - stop++; - } - tmp_len = strlen_m_term(stop); - if (tmp_len == (size_t)-1) { - return false; - } - num_of_strings = entry->num_of_strings; - if (!add_string_to_array(mem_ctx, stop, &entry->strings, - &num_of_strings)) { - return false; - } - if (num_of_strings > 0xffff) { - return false; - } - entry->num_of_strings = num_of_strings; - entry->strings_len += tmp_len; - } else if ( 0 == strncmp( start, "DAT", stop - start ) ) { - /* skip past initial ":" */ - stop++; - /* now skip any other leading whitespace */ - while ( isspace( stop[0] ) ) { - stop++; - } - entry->data_length = strlen_m(stop); - entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length); - if (!entry->data.data) { - return false; - } - } else { - /* some other eventlog entry -- not implemented, so dropping on the floor */ - DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) ); - /* For now return true so that we can keep on parsing this mess. Eventually - we will return False here. */ - return true; - } - return true; -} - -/******************************************************************* - calculate the correct fields etc for an eventlog entry -*******************************************************************/ - -size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r) -{ - size_t size = 56; /* static size of integers before buffers start */ - - r->source_name_len = strlen_m_term(r->source_name) * 2; - r->computer_name_len = strlen_m_term(r->computer_name) * 2; - r->strings_len = ndr_size_string_array(r->strings, - r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2; - - /* fix up the eventlog entry structure as necessary */ - r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 ); - r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4; - - if (r->sid_length == 0) { - /* Should not pad to a DWORD boundary for writing out the sid if there is - no SID, so just propagate the padding to pad the data */ - r->padding += r->sid_padding; - r->sid_padding = 0; - } - - size += r->source_name_len; - size += r->computer_name_len; - size += r->sid_padding; - size += r->sid_length; - size += r->strings_len; - size += r->data_length; - size += r->padding; - /* need another copy of length at the end of the data */ - size += sizeof(r->size); - - r->size = size; - - return size; -} - - -/******************************************************************** - ********************************************************************/ - -struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - uint32_t record_number) -{ - struct eventlog_Record_tdb *r; - TDB_DATA data, key; - - int32_t srecno; - enum ndr_err_code ndr_err; - DATA_BLOB blob; - - srecno = record_number; - key.dptr = (unsigned char *)&srecno; - key.dsize = sizeof(int32_t); - - data = tdb_fetch(tdb, key); - if (data.dsize == 0) { - DEBUG(8,("evlog_pull_record_tdb: " - "Can't find a record for the key, record %d\n", - record_number)); - return NULL; - } - - r = talloc_zero(mem_ctx, struct eventlog_Record_tdb); - if (!r) { - goto done; - } - - blob = data_blob_const(data.dptr, data.dsize); - - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r, - (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb); - - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n", - record_number)); - TALLOC_FREE(r); - goto done; - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(eventlog_Record_tdb, r); - } - - DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n", - record_number)); - done: - SAFE_FREE(data.dptr); - - return r; -} - -/******************************************************************** - ********************************************************************/ - -struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - uint32_t record_number) -{ - struct eventlog_Record_tdb *t; - struct EVENTLOGRECORD *r; - NTSTATUS status; - - r = talloc_zero(mem_ctx, struct EVENTLOGRECORD); - if (!r) { - return NULL; - } - - t = evlog_pull_record_tdb(r, tdb, record_number); - if (!t) { - talloc_free(r); - return NULL; - } - - status = evlog_tdb_entry_to_evt_entry(r, t, r); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(r); - return NULL; - } - - r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, NULL, 0); - - return r; -} - -/******************************************************************** - write an eventlog entry. Note that we have to lock, read next - eventlog, increment, write, write the record, unlock - - coming into this, ee has the eventlog record, and the auxilliary date - (computer name, etc.) filled into the other structure. Before packing - into a record, this routine will calc the appropriate padding, etc., - and then blast out the record in a form that can be read back in - ********************************************************************/ - -NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - struct eventlog_Record_tdb *r, - uint32_t *record_number) -{ - TDB_DATA kbuf, ebuf; - DATA_BLOB blob; - enum ndr_err_code ndr_err; - int ret; - - if (!r) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!can_write_to_eventlog(tdb, r->size)) { - return NT_STATUS_EVENTLOG_CANT_START; - } - - /* need to read the record number and insert it into the entry here */ - - /* lock */ - ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1); - if (ret == -1) { - return NT_STATUS_LOCK_NOT_GRANTED; - } - - /* read */ - r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD); - - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r, - (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); - return ndr_map_error2ntstatus(ndr_err); - } - - /* increment the record count */ - - kbuf.dsize = sizeof(int32_t); - kbuf.dptr = (uint8_t *)&r->record_number; - - ebuf.dsize = blob.length; - ebuf.dptr = blob.data; - - ret = tdb_store(tdb, kbuf, ebuf, 0); - if (ret == -1) { - tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); - return NT_STATUS_EVENTLOG_FILE_CORRUPT; - } - - ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1); - if (ret == -1) { - tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); - return NT_STATUS_EVENTLOG_FILE_CORRUPT; - } - tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); - - if (record_number) { - *record_number = r->record_number; - } - - return NT_STATUS_OK; -} - -/******************************************************************** - ********************************************************************/ - -NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - struct EVENTLOGRECORD *r, - uint32_t *record_number) -{ - struct eventlog_Record_tdb *t; - NTSTATUS status; - - t = talloc_zero(mem_ctx, struct eventlog_Record_tdb); - if (!t) { - return NT_STATUS_NO_MEMORY; - } - - status = evlog_evt_entry_to_tdb_entry(t, r, t); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(t); - return status; - } - - status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number); - talloc_free(t); - - return status; -} - -/******************************************************************** - ********************************************************************/ - -NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx, - const struct EVENTLOGRECORD *e, - struct eventlog_Record_tdb *t) -{ - uint32_t i; - - ZERO_STRUCTP(t); - - t->size = e->Length; - t->reserved = e->Reserved; - t->record_number = e->RecordNumber; - t->time_generated = e->TimeGenerated; - t->time_written = e->TimeWritten; - t->event_id = e->EventID; - t->event_type = e->EventType; - t->num_of_strings = e->NumStrings; - t->event_category = e->EventCategory; - t->reserved_flags = e->ReservedFlags; - t->closing_record_number = e->ClosingRecordNumber; - - t->stringoffset = e->StringOffset; - t->sid_length = e->UserSidLength; - t->sid_offset = e->UserSidOffset; - t->data_length = e->DataLength; - t->data_offset = e->DataOffset; - - t->source_name_len = 2 * strlen_m_term(e->SourceName); - t->source_name = talloc_strdup(mem_ctx, e->SourceName); - NT_STATUS_HAVE_NO_MEMORY(t->source_name); - - t->computer_name_len = 2 * strlen_m_term(e->Computername); - t->computer_name = talloc_strdup(mem_ctx, e->Computername); - NT_STATUS_HAVE_NO_MEMORY(t->computer_name); - - /* t->sid_padding; */ - if (e->UserSidLength > 0) { - const char *sid_str = NULL; - smb_ucs2_t *dummy = NULL; - sid_str = sid_string_talloc(mem_ctx, &e->UserSid); - t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str); - if (t->sid_length == -1) { - return NT_STATUS_NO_MEMORY; - } - t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length); - NT_STATUS_HAVE_NO_MEMORY(t->sid.data); - } - - t->strings = talloc_array(mem_ctx, const char *, e->NumStrings); - for (i=0; i < e->NumStrings; i++) { - t->strings[i] = talloc_strdup(t->strings, e->Strings[i]); - NT_STATUS_HAVE_NO_MEMORY(t->strings[i]); - } - - t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM); - t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength); - /* t->padding = r->Pad; */ - - return NT_STATUS_OK; -} - -/******************************************************************** - ********************************************************************/ - -NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, - const struct eventlog_Record_tdb *t, - struct EVENTLOGRECORD *e) -{ - uint32_t i; - - ZERO_STRUCTP(e); - - e->Length = t->size; - e->Reserved = t->reserved; - e->RecordNumber = t->record_number; - e->TimeGenerated = t->time_generated; - e->TimeWritten = t->time_written; - e->EventID = t->event_id; - e->EventType = t->event_type; - e->NumStrings = t->num_of_strings; - e->EventCategory = t->event_category; - e->ReservedFlags = t->reserved_flags; - e->ClosingRecordNumber = t->closing_record_number; - - e->StringOffset = t->stringoffset; - e->UserSidLength = t->sid_length; - e->UserSidOffset = t->sid_offset; - e->DataLength = t->data_length; - e->DataOffset = t->data_offset; - - e->SourceName = talloc_strdup(mem_ctx, t->source_name); - NT_STATUS_HAVE_NO_MEMORY(e->SourceName); - - e->Computername = talloc_strdup(mem_ctx, t->computer_name); - NT_STATUS_HAVE_NO_MEMORY(e->Computername); - - if (t->sid_length > 0) { - const char *sid_str = NULL; - size_t len; - if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, - t->sid.data, t->sid.length, - (void **)&sid_str, &len, false)) { - return NT_STATUS_INVALID_SID; - } - if (len > 0) { - e->UserSid = *string_sid_talloc(mem_ctx, sid_str); - } - } - - e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings); - for (i=0; i < t->num_of_strings; i++) { - e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]); - NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]); - } - - e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length); - e->Pad = talloc_strdup(mem_ctx, ""); - NT_STATUS_HAVE_NO_MEMORY(e->Pad); - - e->Length2 = t->size; - - return NT_STATUS_OK; -} -- cgit From 47bda3f3c7095044ae4c9b1535198be6d052060d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 17:15:15 +0200 Subject: s3-eventlog: split out evlog_convert_tdb_to_evt(). Guenther --- source3/include/proto.h | 4 +++ source3/lib/eventlog/eventlog.c | 74 +++++++++++++++++++++++++++++++++++++++++ source3/utils/net_eventlog.c | 54 ++---------------------------- 3 files changed, 80 insertions(+), 52 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index c8c2ece968..b22bb06512 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5874,6 +5874,10 @@ NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx, NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, const struct eventlog_Record_tdb *t, struct EVENTLOGRECORD *e); +NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx, + ELOG_TDB *etdb, + DATA_BLOB *blob_p, + uint32_t *num_records_p); /* The following definitions come from rpc_server/srv_eventlog_nt.c */ diff --git a/source3/lib/eventlog/eventlog.c b/source3/lib/eventlog/eventlog.c index f83c4fc3b8..11cb28a120 100644 --- a/source3/lib/eventlog/eventlog.c +++ b/source3/lib/eventlog/eventlog.c @@ -958,3 +958,77 @@ NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx, + ELOG_TDB *etdb, + DATA_BLOB *blob_p, + uint32_t *num_records_p) +{ + NTSTATUS status = NT_STATUS_OK; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + uint32_t num_records = 0; + struct EVENTLOG_EVT_FILE evt; + uint32_t count = 1; + size_t endoffset = 0; + + ZERO_STRUCT(evt); + + while (1) { + + struct eventlog_Record_tdb *r; + struct EVENTLOGRECORD e; + + r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count); + if (!r) { + break; + } + + status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0); + + ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records); + count++; + } + + evt.hdr.StartOffset = 0x30; + evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset; + evt.hdr.CurrentRecordNumber = count; + evt.hdr.OldestRecordNumber = 1; + evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE); + evt.hdr.Flags = 0; + evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION); + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr); + } + + evt.eof.BeginRecord = 0x30; + evt.eof.EndRecord = evt.hdr.StartOffset + endoffset; + evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber; + evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber; + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof); + } + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &evt, + (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + goto done; + } + + *blob_p = blob; + *num_records_p = num_records; + + done: + return status; +} diff --git a/source3/utils/net_eventlog.c b/source3/utils/net_eventlog.c index 197a7cd330..b86be6d48b 100644 --- a/source3/utils/net_eventlog.c +++ b/source3/utils/net_eventlog.c @@ -182,13 +182,9 @@ static int net_eventlog_export(struct net_context *c, int argc, int ret = -1; NTSTATUS status; TALLOC_CTX *ctx = talloc_stackframe(); - enum ndr_err_code ndr_err; DATA_BLOB blob; uint32_t num_records = 0; - struct EVENTLOG_EVT_FILE evt; ELOG_TDB *etdb = NULL; - uint32_t count = 1; - size_t endoffset = 0; if (argc < 2 || c->display_usage) { d_fprintf(stderr, "usage: net eventlog export \n"); @@ -201,54 +197,8 @@ static int net_eventlog_export(struct net_context *c, int argc, goto done; } - ZERO_STRUCT(evt); - - while (1) { - - struct eventlog_Record_tdb *r; - struct EVENTLOGRECORD e; - - r = evlog_pull_record_tdb(ctx, etdb->tdb, count); - if (!r) { - break; - } - - status = evlog_tdb_entry_to_evt_entry(ctx, r, &e); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0); - - ADD_TO_ARRAY(ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records); - count++; - } - - evt.hdr.StartOffset = 0x30; - evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset; - evt.hdr.CurrentRecordNumber = count; - evt.hdr.OldestRecordNumber = 1; - evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE); - evt.hdr.Flags = 0; - evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION); - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr); - } - - evt.eof.BeginRecord = 0x30; - evt.eof.EndRecord = evt.hdr.StartOffset + endoffset; - evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber; - evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber; - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof); - } - - ndr_err = ndr_push_struct_blob(&blob, ctx, NULL, &evt, - (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - d_fprintf(stderr, "evt push failed: %s\n", ndr_errstr(ndr_err)); + status = evlog_convert_tdb_to_evt(ctx, etdb, &blob, &num_records); + if (!NT_STATUS_IS_OK(status)) { goto done; } -- cgit From f3d33cd81d53050f53fc46239bbb7f559dffd42c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 21:33:01 +0200 Subject: Convert rpc_transport_np_init to tevent_req --- source3/include/proto.h | 10 ++--- source3/rpc_client/rpc_transport_np.c | 65 ++++++++++++++++----------------- source3/rpc_client/rpc_transport_smbd.c | 14 +++---- 3 files changed, 43 insertions(+), 46 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b22bb06512..ad607cee69 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5391,11 +5391,11 @@ NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx, /* The following definitions come from rpc_client/rpc_transport_np.c */ -struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax); -NTSTATUS rpc_transport_np_init_recv(struct async_req *req, +struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const struct ndr_syntax_id *abstract_syntax); +NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult); NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 730a309acf..40d68dd2ea 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -273,28 +273,28 @@ struct rpc_transport_np_init_state { static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq); -struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax) +struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const struct ndr_syntax_id *abstract_syntax) { - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct rpc_transport_np_init_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_transport_np_init_state)) { + req = tevent_req_create(mem_ctx, &state, + struct rpc_transport_np_init_state); + if (req == NULL) { return NULL; } state->transport = talloc(state, struct rpc_cli_transport); - if (state->transport == NULL) { - goto fail; + if (tevent_req_nomem(state->transport, req)) { + return tevent_req_post(req, ev); } state->transport_np = talloc(state->transport, struct rpc_transport_np_state); - if (state->transport_np == NULL) { - goto fail; + if (tevent_req_nomem(state->transport_np, req)) { + return tevent_req_post(req, ev); } state->transport->priv = state->transport_np; @@ -306,47 +306,43 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, state, ev, cli, state->transport_np->pipe_name, 0, DESIRED_ACCESS_PIPE, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0); - if (subreq == NULL) { - goto fail; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, - result); - return result; - - fail: - TALLOC_FREE(result); - return NULL; + req); + return req; } static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct rpc_transport_np_init_state *state = talloc_get_type_abort( - req->private_data, struct rpc_transport_np_init_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_transport_np_init_state *state = tevent_req_data( + req, struct rpc_transport_np_init_state); NTSTATUS status; status = cli_ntcreate_recv(subreq, &state->transport_np->fnum); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } talloc_set_destructor(state->transport_np, rpc_transport_np_state_destructor); - async_req_done(req); + tevent_req_done(req); } -NTSTATUS rpc_transport_np_init_recv(struct async_req *req, +NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult) { - struct rpc_transport_np_init_state *state = talloc_get_type_abort( - req->private_data, struct rpc_transport_np_init_state); + struct rpc_transport_np_init_state *state = tevent_req_data( + req, struct rpc_transport_np_init_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } @@ -367,8 +363,8 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; - NTSTATUS status; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; ev = event_context_init(frame); if (ev == NULL) { @@ -382,8 +378,9 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = rpc_transport_np_init_recv(req, mem_ctx, presult); diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 5a5433fb1c..16ec17e132 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -573,14 +573,15 @@ struct rpc_transport_smbd_init_state { struct rpc_transport_smbd_state *transport_smbd; }; -static void rpc_transport_smbd_init_done(struct async_req *subreq); +static void rpc_transport_smbd_init_done(struct tevent_req *subreq); struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_cli_smbd_conn *conn, const struct ndr_syntax_id *abstract_syntax) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct rpc_transport_smbd_init_state *state; if (!async_req_setup(mem_ctx, &result, &state, @@ -610,8 +611,7 @@ struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_transport_smbd_init_done; - subreq->async.priv = result; + tevent_req_set_callback(subreq, rpc_transport_smbd_init_done, result); return result; fail: @@ -619,10 +619,10 @@ struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, return NULL; } -static void rpc_transport_smbd_init_done(struct async_req *subreq) +static void rpc_transport_smbd_init_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct rpc_transport_smbd_init_state *state = talloc_get_type_abort( req->private_data, struct rpc_transport_smbd_init_state); NTSTATUS status; -- cgit From bfacecc17b6f12fd80aa915bcfdbf2af7fb674e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 21:42:01 +0200 Subject: Convert get_anon_ipc to tevent_req --- source3/rpc_client/rpc_transport_smbd.c | 75 +++++++++++++++------------------ 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 16ec17e132..9e10be8411 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -132,50 +132,45 @@ static void get_anon_ipc_negprot_done(struct tevent_req *subreq); static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq); static void get_anon_ipc_tcon_done(struct tevent_req *subreq); -static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli) +static struct tevent_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) { - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct get_anon_ipc_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct get_anon_ipc_state)) { + req = tevent_req_create(mem_ctx, &state, struct get_anon_ipc_state); + if (req == NULL) { return NULL; } - state->ev = ev; state->cli = cli; subreq = cli_negprot_send(state, ev, cli); - if (subreq == NULL) { - goto fail; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, get_anon_ipc_negprot_done, result); - return result; - fail: - TALLOC_FREE(result); - return NULL; + tevent_req_set_callback(subreq, get_anon_ipc_negprot_done, req); + return req; } static void get_anon_ipc_negprot_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct get_anon_ipc_state *state = talloc_get_type_abort( - req->private_data, struct get_anon_ipc_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct get_anon_ipc_state *state = tevent_req_data( + req, struct get_anon_ipc_state); NTSTATUS status; status = cli_negprot_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } subreq = cli_session_setup_guest_send(state, state->ev, state->cli); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, get_anon_ipc_sesssetup_done, req); @@ -183,22 +178,22 @@ static void get_anon_ipc_negprot_done(struct tevent_req *subreq) static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct get_anon_ipc_state *state = talloc_get_type_abort( - req->private_data, struct get_anon_ipc_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct get_anon_ipc_state *state = tevent_req_data( + req, struct get_anon_ipc_state); NTSTATUS status; status = cli_session_setup_guest_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } subreq = cli_tcon_andx_send(state, state->ev, state->cli, "IPC$", "IPC", NULL, 0); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, get_anon_ipc_tcon_done, req); @@ -206,22 +201,22 @@ static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq) static void get_anon_ipc_tcon_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); NTSTATUS status; status = cli_tcon_andx_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS get_anon_ipc_recv(struct async_req *req) +static NTSTATUS get_anon_ipc_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } struct rpc_cli_smbd_conn_init_state { @@ -229,7 +224,7 @@ struct rpc_cli_smbd_conn_init_state { struct rpc_cli_smbd_conn *conn; }; -static void rpc_cli_smbd_conn_init_done(struct async_req *subreq); +static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq); struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -238,7 +233,8 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, void *priv), void *priv) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct rpc_cli_smbd_conn_init_state *state; int smb_sock[2]; int stdout_pipe[2]; @@ -337,8 +333,7 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, goto nomem; } - subreq->async.fn = rpc_cli_smbd_conn_init_done; - subreq->async.priv = result; + tevent_req_set_callback(subreq, rpc_cli_smbd_conn_init_done, result); return result; nomem: @@ -363,10 +358,10 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, return NULL; } -static void rpc_cli_smbd_conn_init_done(struct async_req *subreq) +static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); NTSTATUS status; status = get_anon_ipc_recv(subreq); -- cgit From 8a2112c942d312ca855c0301baab825cabd97caa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 21:53:16 +0200 Subject: Convert rpc_cli_smbd_conn_init to tevent_req --- source3/include/proto.h | 14 +++---- source3/rpc_client/rpc_transport_smbd.c | 71 ++++++++++++++++----------------- 2 files changed, 41 insertions(+), 44 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index ad607cee69..2172f2abd9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5405,13 +5405,13 @@ struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p); /* The following definitions come from rpc_client/rpc_transport_smbd.c */ -struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - void (*stdout_callback)(char *buf, - size_t len, - void *priv), - void *priv); -NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req, +struct tevent_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv); +NTSTATUS rpc_cli_smbd_conn_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_smbd_conn **pconn); NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 9e10be8411..fa2f9d8f91 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -226,15 +226,14 @@ struct rpc_cli_smbd_conn_init_state { static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq); -struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - void (*stdout_callback)(char *buf, - size_t len, - void *priv), - void *priv) +struct tevent_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv) { - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct rpc_cli_smbd_conn_init_state *state; int smb_sock[2]; int stdout_pipe[2]; @@ -244,20 +243,21 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, smb_sock[0] = smb_sock[1] = stdout_pipe[0] = stdout_pipe[1] = -1; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_cli_smbd_conn_init_state)) { + req = tevent_req_create(mem_ctx, &state, + struct rpc_cli_smbd_conn_init_state); + if (req == NULL) { return NULL; } state->ev = ev; state->conn = talloc(state, struct rpc_cli_smbd_conn); - if (state->conn == NULL) { - goto nomem; + if (tevent_req_nomem(state->conn, req)) { + return tevent_req_post(req, ev); } state->conn->cli = cli_initialise(); - if (state->conn->cli == NULL) { - goto nomem; + if (tevent_req_nomem(state->conn->cli, req)) { + return tevent_req_post(req, ev); } state->conn->stdout_fd = -1; state->conn->stdout_callback.fn = stdout_callback; @@ -324,20 +324,19 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, stdout_pipe[1] = -1; subreq = get_anon_ipc_send(state, ev, state->conn->cli); - if (subreq == NULL) { - goto nomem; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } if (event_add_fd(ev, state, state->conn->stdout_fd, EVENT_FD_READ, rpc_cli_smbd_stdout_reader, state->conn) == NULL) { - goto nomem; + status = NT_STATUS_NO_MEMORY; + goto post_status; } - tevent_req_set_callback(subreq, rpc_cli_smbd_conn_init_done, result); - return result; + tevent_req_set_callback(subreq, rpc_cli_smbd_conn_init_done, req); + return req; - nomem: - status = NT_STATUS_NO_MEMORY; post_status: if (smb_sock[0] != -1) { close(smb_sock[0]); @@ -351,37 +350,34 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, if (stdout_pipe[1] != -1) { close(stdout_pipe[1]); } - if (async_post_ntstatus(result, ev, status)) { - return result; - } - TALLOC_FREE(result); - return NULL; + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); } static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); NTSTATUS status; status = get_anon_ipc_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req, +NTSTATUS rpc_cli_smbd_conn_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_smbd_conn **pconn) { - struct rpc_cli_smbd_conn_init_state *state = talloc_get_type_abort( - req->private_data, struct rpc_cli_smbd_conn_init_state); + struct rpc_cli_smbd_conn_init_state *state = tevent_req_data( + req, struct rpc_cli_smbd_conn_init_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *pconn = talloc_move(mem_ctx, &state->conn); @@ -397,7 +393,7 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status; ev = event_context_init(frame); @@ -412,8 +408,9 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = rpc_cli_smbd_conn_init_recv(req, mem_ctx, pconn); -- cgit From a3f24d91c53751835ed309a7c599c367cc4b0c24 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 21:58:41 +0200 Subject: Convert rpc_transport_smbd_init to tevent_req --- source3/include/proto.h | 10 ++--- source3/rpc_client/rpc_transport_smbd.c | 66 ++++++++++++++++----------------- 2 files changed, 37 insertions(+), 39 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 2172f2abd9..b210a3d73b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5421,11 +5421,11 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, void *priv), void *priv); -struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_cli_smbd_conn *conn, - const struct ndr_syntax_id *abstract_syntax); -NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, +struct tevent_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax); +NTSTATUS rpc_transport_smbd_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult); NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index fa2f9d8f91..171048ae29 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -567,56 +567,53 @@ struct rpc_transport_smbd_init_state { static void rpc_transport_smbd_init_done(struct tevent_req *subreq); -struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_cli_smbd_conn *conn, - const struct ndr_syntax_id *abstract_syntax) +struct tevent_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax) { - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct rpc_transport_smbd_init_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_transport_smbd_init_state)) { + req = tevent_req_create(mem_ctx, &state, + struct rpc_transport_smbd_init_state); + if (req == NULL) { return NULL; } state->transport = talloc(state, struct rpc_cli_transport); - if (state->transport == NULL) { - goto fail; + if (tevent_req_nomem(state->transport, req)) { + return tevent_req_post(req, ev); } state->transport_smbd = talloc(state->transport, struct rpc_transport_smbd_state); - if (state->transport_smbd == NULL) { - goto fail; + if (tevent_req_nomem(state->transport_smbd, req)) { + return tevent_req_post(req, ev); } state->transport_smbd->conn = conn; state->transport->priv = state->transport_smbd; if (event_add_fd(ev, state, conn->stdout_fd, EVENT_FD_READ, rpc_cli_smbd_stdout_reader, conn) == NULL) { - goto fail; + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, ev); } subreq = rpc_transport_np_init_send(state, ev, conn->cli, abstract_syntax); - if (subreq == NULL) { - goto fail; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, rpc_transport_smbd_init_done, result); - return result; - - fail: - TALLOC_FREE(result); - return NULL; + tevent_req_set_callback(subreq, rpc_transport_smbd_init_done, req); + return req; } static void rpc_transport_smbd_init_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct rpc_transport_smbd_init_state *state = talloc_get_type_abort( - req->private_data, struct rpc_transport_smbd_init_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_transport_smbd_init_state *state = tevent_req_data( + req, struct rpc_transport_smbd_init_state); NTSTATUS status; status = rpc_transport_np_init_recv( @@ -624,21 +621,21 @@ static void rpc_transport_smbd_init_done(struct tevent_req *subreq) &state->transport_smbd->sub_transp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, +NTSTATUS rpc_transport_smbd_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult) { - struct rpc_transport_smbd_init_state *state = talloc_get_type_abort( - req->private_data, struct rpc_transport_smbd_init_state); + struct rpc_transport_smbd_init_state *state = tevent_req_data( + req, struct rpc_transport_smbd_init_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } @@ -660,7 +657,7 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status; ev = event_context_init(frame); @@ -675,8 +672,9 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = rpc_transport_smbd_init_recv(req, mem_ctx, presult); -- cgit From d0c307af56006d6fb898e395613d7e9c29b84116 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 21:45:04 +0200 Subject: s3-net: Fix Bug #5329: add "net rpc service delete/create". Patch from Danny Tylman . Guenther --- source3/utils/net_rpc_service.c | 204 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) (limited to 'source3') diff --git a/source3/utils/net_rpc_service.c b/source3/utils/net_rpc_service.c index bcb1a00dab..57a721e55b 100644 --- a/source3/utils/net_rpc_service.c +++ b/source3/utils/net_rpc_service.c @@ -631,6 +631,161 @@ done: /******************************************************************** ********************************************************************/ +static NTSTATUS rpc_service_delete_internal(struct net_context *c, + const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ + struct policy_handle hSCM, hService; + WERROR result = WERR_GENERAL_FAILURE; + NTSTATUS status; + + if (argc != 1 ) { + d_printf("Usage: net rpc service delete \n"); + return NT_STATUS_OK; + } + + /* Open the Service Control Manager */ + status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx, + pipe_hnd->srv_name_slash, + NULL, + SC_RIGHT_MGR_ENUMERATE_SERVICE, + &hSCM, + &result); + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) { + d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n", + win_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Open the Service */ + + status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx, + &hSCM, + argv[0], + SERVICE_ALL_ACCESS, + &hService, + &result); + + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Failed to open service. [%s]\n", + win_errstr(result)); + goto done; + } + + /* Delete the Service */ + + status = rpccli_svcctl_DeleteService(pipe_hnd, mem_ctx, + &hService, + &result); + + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Delete service request failed. [%s]\n", + win_errstr(result)); + goto done; + } + + d_printf("Successfully deleted Service: %s\n", argv[0]); + + done: + if (is_valid_policy_hnd(&hService)) { + rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL); + } + if (is_valid_policy_hnd(&hSCM)) { + rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL); + } + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_create_internal(struct net_context *c, + const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ + struct policy_handle hSCM, hService; + WERROR result = WERR_GENERAL_FAILURE; + NTSTATUS status; + const char *ServiceName; + const char *DisplayName; + const char *binary_path; + + if (argc != 3) { + d_printf("Usage: net rpc service create \n"); + return NT_STATUS_OK; + } + + /* Open the Service Control Manager */ + status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx, + pipe_hnd->srv_name_slash, + NULL, + SC_RIGHT_MGR_CREATE_SERVICE, + &hSCM, + &result); + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) { + d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n", + win_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Create the service */ + + ServiceName = argv[0]; + DisplayName = argv[1]; + binary_path = argv[2]; + + status = rpccli_svcctl_CreateServiceW(pipe_hnd, mem_ctx, + &hSCM, + ServiceName, + DisplayName, + SERVICE_ALL_ACCESS, + SERVICE_TYPE_WIN32_OWN_PROCESS, + SVCCTL_DEMAND_START, + SVCCTL_SVC_ERROR_NORMAL, + binary_path, + NULL, /* LoadOrderGroupKey */ + NULL, /* TagId */ + NULL, /* dependencies */ + 0, /* dependencies_size */ + NULL, /* service_start_name */ + NULL, /* password */ + 0, /* password_size */ + &hService, + &result); + + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Create service request failed. [%s]\n", + win_errstr(result)); + goto done; + } + + d_printf("Successfully created Service: %s\n", argv[0]); + + done: + if (is_valid_policy_hnd(&hService)) { + rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL); + } + if (is_valid_policy_hnd(&hSCM)) { + rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL); + } + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + static int rpc_service_list(struct net_context *c, int argc, const char **argv ) { if (c->display_usage) { @@ -727,6 +882,38 @@ static int rpc_service_status(struct net_context *c, int argc, const char **argv /******************************************************************** ********************************************************************/ +static int rpc_service_delete(struct net_context *c, int argc, const char **argv) +{ + if (c->display_usage) { + d_printf("Usage:\n" + "net rpc service delete \n" + " Delete a Win32 service\n"); + return 0; + } + + return run_rpc_command(c, NULL, &ndr_table_svcctl.syntax_id, 0, + rpc_service_delete_internal, argc, argv); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_create(struct net_context *c, int argc, const char **argv) +{ + if (c->display_usage) { + d_printf("Usage:\n" + "net rpc service create \n" + " Create a Win32 service\n"); + return 0; + } + + return run_rpc_command(c, NULL, &ndr_table_svcctl.syntax_id, 0, + rpc_service_create_internal, argc, argv); +} + +/******************************************************************** +********************************************************************/ + int net_rpc_service(struct net_context *c, int argc, const char **argv) { struct functable func[] = { @@ -778,6 +965,23 @@ int net_rpc_service(struct net_context *c, int argc, const char **argv) "net rpc service status\n" " View current status of a service" }, + { + "delete", + rpc_service_delete, + NET_TRANSPORT_RPC, + "Delete a service", + "net rpc service delete\n" + " Deletes a service" + }, + { + "create", + rpc_service_create, + NET_TRANSPORT_RPC, + "Create a service", + "net rpc service create\n" + " Creates a service" + }, + {NULL, NULL, 0, NULL, NULL} }; -- cgit From 9c89aee5f34aff8b3d54ceafa1a5802b60088b49 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 22:39:55 +0200 Subject: Convert cli_pull to tevent_req --- source3/include/proto.h | 18 ++++----- source3/libsmb/clireadwrite.c | 85 ++++++++++++++++++++----------------------- 2 files changed, 49 insertions(+), 54 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b210a3d73b..5f77524bb8 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2779,15 +2779,15 @@ struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, off_t offset, size_t size); NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, uint8_t **rcvbuf); -struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint16_t fnum, off_t start_offset, - SMB_OFF_T size, size_t window_size, - NTSTATUS (*sink)(char *buf, size_t n, - void *priv), - void *priv); -NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received); +struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, off_t start_offset, + SMB_OFF_T size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, + void *priv), + void *priv); +NTSTATUS cli_pull_recv(struct tevent_req *req, SMB_OFF_T *received); NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, off_t start_offset, SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, void *priv), diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index bb1e2f66c2..b64a5d308f 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -239,7 +239,7 @@ struct cli_pull_subreq { */ struct cli_pull_state { - struct async_req *req; + struct tevent_req *req; struct event_context *ev; struct cli_state *cli; @@ -278,13 +278,13 @@ struct cli_pull_state { SMB_OFF_T pushed; }; -static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) +static char *cli_pull_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) { - struct cli_pull_state *state = talloc_get_type_abort( - req->private_data, struct cli_pull_state); + struct cli_pull_state *state = tevent_req_data( + req, struct cli_pull_state); char *result; - result = async_req_print(mem_ctx, req); + result = tevent_req_print(mem_ctx, req); if (result == NULL) { return NULL; } @@ -300,25 +300,25 @@ static void cli_pull_read_done(struct tevent_req *read_req); * Prepare an async pull request */ -struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint16_t fnum, off_t start_offset, - SMB_OFF_T size, size_t window_size, - NTSTATUS (*sink)(char *buf, size_t n, - void *priv), - void *priv) +struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, off_t start_offset, + SMB_OFF_T size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, + void *priv), + void *priv) { - struct async_req *result; + struct tevent_req *req; struct cli_pull_state *state; int i; - if (!async_req_setup(mem_ctx, &result, &state, - struct cli_pull_state)) { + req = tevent_req_create(mem_ctx, &state, struct cli_pull_state); + if (req == NULL) { return NULL; } - result->print = cli_pull_print; - state->req = result; + tevent_req_set_print_fn(req, cli_pull_print); + state->req = req; state->cli = cli; state->ev = ev; @@ -332,10 +332,8 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->top_req = 0; if (size == 0) { - if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) { - goto failed; - } - return result; + tevent_req_done(req); + return tevent_req_post(req, ev); } state->chunk_size = cli_read_max_bufsize(cli); @@ -372,14 +370,13 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, if (subreq->req == NULL) { goto failed; } - tevent_req_set_callback(subreq->req, cli_pull_read_done, - result); + tevent_req_set_callback(subreq->req, cli_pull_read_done, req); state->requested += request_thistime; } - return result; + return req; failed: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } @@ -390,10 +387,10 @@ failed: static void cli_pull_read_done(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct cli_pull_state *state = talloc_get_type_abort( - req->private_data, struct cli_pull_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_pull_state *state = tevent_req_data( + req, struct cli_pull_state); struct cli_pull_subreq *pull_subreq = NULL; NTSTATUS status; int i; @@ -406,14 +403,14 @@ static void cli_pull_read_done(struct tevent_req *subreq) } if (i == state->num_reqs) { /* Huh -- received something we did not send?? */ - async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } status = cli_read_andx_recv(subreq, &pull_subreq->received, &pull_subreq->buf); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(state->req, status); + tevent_req_nterror(state->req, status); return; } @@ -447,7 +444,7 @@ static void cli_pull_read_done(struct tevent_req *subreq) status = state->sink((char *)top_subreq->buf, top_subreq->received, state->priv); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(state->req, status); + tevent_req_nterror(state->req, status); return; } state->pushed += top_subreq->received; @@ -475,7 +472,7 @@ static void cli_pull_read_done(struct tevent_req *subreq) state->start_offset + state->requested, request_thistime); - if (async_req_nomem(new_req, state->req)) { + if (tevent_req_nomem(new_req, state->req)) { return; } tevent_req_set_callback(new_req, cli_pull_read_done, @@ -488,16 +485,16 @@ static void cli_pull_read_done(struct tevent_req *subreq) state->top_req = (state->top_req+1) % state->num_reqs; } - async_req_done(req); + tevent_req_done(req); } -NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) +NTSTATUS cli_pull_recv(struct tevent_req *req, SMB_OFF_T *received) { - struct cli_pull_state *state = talloc_get_type_abort( - req->private_data, struct cli_pull_state); + struct cli_pull_state *state = tevent_req_data( + req, struct cli_pull_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *received = state->pushed; @@ -511,7 +508,7 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status = NT_STATUS_OK; if (cli_has_async_calls(cli)) { @@ -535,11 +532,9 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - if (event_loop_once(ev) == -1) { - status = map_nt_error_from_unix(errno); - goto fail; - } + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_pull_recv(req, received); -- cgit From cf7d26933b630006428c827df69728f4eab01e37 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 22:54:28 +0200 Subject: Convert cli_push to tevent_req Metze, please check! Thanks, Volker --- source3/include/proto.h | 16 +++--- source3/libsmb/clireadwrite.c | 127 +++++++++++++++++++----------------------- 2 files changed, 66 insertions(+), 77 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 5f77524bb8..678f087374 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2815,14 +2815,14 @@ struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, off_t offset, size_t size); NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten); -struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, - uint16_t fnum, uint16_t mode, - off_t start_offset, size_t window_size, - size_t (*source)(uint8_t *buf, size_t n, - void *priv), - void *priv); -NTSTATUS cli_push_recv(struct async_req *req); +struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, uint16_t mode, + off_t start_offset, size_t window_size, + size_t (*source)(uint8_t *buf, size_t n, + void *priv), + void *priv); +NTSTATUS cli_push_recv(struct tevent_req *req); NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, off_t start_offset, size_t window_size, size_t (*source)(uint8_t *buf, size_t n, void *priv), diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index b64a5d308f..1d2f5f79ec 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -927,20 +927,19 @@ struct cli_writeall_state { static void cli_writeall_written(struct tevent_req *req); -static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint16_t fnum, - uint16_t mode, - const uint8_t *buf, - off_t offset, size_t size) +static struct tevent_req *cli_writeall_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint16_t mode, + const uint8_t *buf, + off_t offset, size_t size) { - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct cli_writeall_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct cli_writeall_state)) { + req = tevent_req_create(mem_ctx, &state, struct cli_writeall_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -955,44 +954,40 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, subreq = cli_write_andx_send(state, state->ev, state->cli, state->fnum, state->mode, state->buf, state->offset, state->size); - if (subreq == NULL) { - goto fail; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_writeall_written, result); - return result; - - fail: - TALLOC_FREE(result); - return NULL; + tevent_req_set_callback(subreq, cli_writeall_written, req); + return req; } static void cli_writeall_written(struct tevent_req *subreq) { - struct async_req *req = tevent_req_callback_data( - subreq, struct async_req); - struct cli_writeall_state *state = talloc_get_type_abort( - req->private_data, struct cli_writeall_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_writeall_state *state = tevent_req_data( + req, struct cli_writeall_state); NTSTATUS status; size_t written, to_write; status = cli_write_andx_recv(subreq, &written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } state->written += written; if (state->written > state->size) { - async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } to_write = state->size - state->written; if (to_write == 0) { - async_req_done(req); + tevent_req_done(req); return; } @@ -1000,20 +995,19 @@ static void cli_writeall_written(struct tevent_req *subreq) state->mode, state->buf + state->written, state->offset + state->written, to_write); - if (subreq == NULL) { - async_req_nterror(req, NT_STATUS_NO_MEMORY); + if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, cli_writeall_written, req); } -static NTSTATUS cli_writeall_recv(struct async_req *req) +static NTSTATUS cli_writeall_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } struct cli_push_write_state { - struct async_req *req;/* This is the main request! Not the subreq */ + struct tevent_req *req;/* This is the main request! Not the subreq */ uint32_t idx; off_t ofs; uint8_t *buf; @@ -1044,14 +1038,14 @@ struct cli_push_state { struct cli_push_write_state **reqs; }; -static void cli_push_written(struct async_req *req); +static void cli_push_written(struct tevent_req *req); -static bool cli_push_write_setup(struct async_req *req, +static bool cli_push_write_setup(struct tevent_req *req, struct cli_push_state *state, uint32_t idx) { struct cli_push_write_state *substate; - struct async_req *subreq; + struct tevent_req *subreq; substate = talloc(state->reqs, struct cli_push_write_state); if (!substate) { @@ -1085,8 +1079,7 @@ static bool cli_push_write_setup(struct async_req *req, talloc_free(substate); return false; } - subreq->async.fn = cli_push_written; - subreq->async.priv = substate; + tevent_req_set_callback(subreq, cli_push_written, substate); state->reqs[idx] = substate; state->pending += 1; @@ -1095,20 +1088,20 @@ static bool cli_push_write_setup(struct async_req *req, return true; } -struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - struct cli_state *cli, - uint16_t fnum, uint16_t mode, - off_t start_offset, size_t window_size, - size_t (*source)(uint8_t *buf, size_t n, - void *priv), - void *priv) +struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, uint16_t mode, + off_t start_offset, size_t window_size, + size_t (*source)(uint8_t *buf, size_t n, + void *priv), + void *priv) { - struct async_req *req; + struct tevent_req *req; struct cli_push_state *state; uint32_t i; - if (!async_req_setup(mem_ctx, &req, &state, - struct cli_push_state)) { + req = tevent_req_create(mem_ctx, &state, struct cli_push_state); + if (req == NULL) { return NULL; } state->cli = cli; @@ -1151,26 +1144,24 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } if (state->pending == 0) { - if (!async_post_ntstatus(req, ev, NT_STATUS_OK)) { - goto failed; - } - return req; + tevent_req_done(req); + return tevent_req_post(req, ev); } return req; failed: - TALLOC_FREE(req); - return NULL; + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, ev); } -static void cli_push_written(struct async_req *subreq) +static void cli_push_written(struct tevent_req *subreq) { - struct cli_push_write_state *substate = talloc_get_type_abort( - subreq->async.priv, struct cli_push_write_state); - struct async_req *req = substate->req; - struct cli_push_state *state = talloc_get_type_abort( - req->private_data, struct cli_push_state); + struct cli_push_write_state *substate = tevent_req_callback_data( + subreq, struct cli_push_write_state); + struct tevent_req *req = substate->req; + struct cli_push_state *state = tevent_req_data( + req, struct cli_push_state); NTSTATUS status; uint32_t idx = substate->idx; @@ -1181,26 +1172,26 @@ static void cli_push_written(struct async_req *subreq) TALLOC_FREE(subreq); TALLOC_FREE(substate); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } if (!state->eof) { if (!cli_push_write_setup(req, state, idx)) { - async_req_nomem(NULL, req); + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } if (state->pending == 0) { - async_req_done(req); + tevent_req_done(req); return; } } -NTSTATUS cli_push_recv(struct async_req *req) +NTSTATUS cli_push_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, @@ -1210,7 +1201,7 @@ NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status = NT_STATUS_OK; if (cli_has_async_calls(cli)) { @@ -1234,11 +1225,9 @@ NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - if (event_loop_once(ev) == -1) { - status = map_nt_error_from_unix(errno); - goto fail; - } + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; } status = cli_push_recv(req); -- cgit From ccd293ba0e7eede1115c6f2f7de36bc38b59c02f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Apr 2009 23:03:59 +0200 Subject: Remove async_req --- source3/Makefile.in | 3 +-- source3/include/includes.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 8b9bcbf9c6..80ebf0c84b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -363,8 +363,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o \ lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o \ lib/interfaces.o lib/memcache.o \ - lib/util_transfer_file.o ../lib/async_req/async_req.o \ - ../lib/async_req/async_sock.o ../lib/async_req/async_req_ntstatus.o \ + lib/util_transfer_file.o ../lib/async_req/async_sock.o \ $(TDB_LIB_OBJ) \ $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/interface.o lib/pidfile.o \ diff --git a/source3/include/includes.h b/source3/include/includes.h index 497034b62c..433818d9ef 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -646,7 +646,6 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "ctdbd_conn.h" #include "../lib/util/talloc_stack.h" #include "memcache.h" -#include "../lib/async_req/async_req_ntstatus.h" #include "async_smb.h" #include "../lib/async_req/async_sock.h" #include "services.h" -- cgit From d8a6ea8141fba4876b6674806b629748ecf41876 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Apr 2009 23:21:41 +0200 Subject: s3-svcctl: Fix _svcctl_EnumServicesStatusW (again). The final plan is to use the same macro based code that we have in spoolss to handle the buffers and calculate the buffer-sizes. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index ddfe0df10b..1850dcb612 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -466,9 +466,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p, } blob = ndr_push_blob(ndr); - if (blob.length >= r->in.offered) { - memcpy(r->out.service, blob.data, r->in.offered); - } + memcpy(r->out.service, blob.data, r->in.offered); } *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; -- cgit From acd7fef984cba906163b7114a087ca3904e47566 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 9 Apr 2009 13:27:08 +0200 Subject: s3-svcctl: Fix _svcctl_Set/GetServiceObjectSecurity after IDL changes. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 1850dcb612..8ed308ad6b 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -872,7 +872,7 @@ WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p, *r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 ); - if ( *r->out.needed > r->in.buffer_size ) { + if ( *r->out.needed > r->in.offered) { ZERO_STRUCTP( &r->out.buffer ); return WERR_INSUFFICIENT_BUFFER; } @@ -932,7 +932,8 @@ WERROR _svcctl_SetServiceObjectSecurity(pipes_struct *p, /* read the security descfriptor */ status = unmarshall_sec_desc(p->mem_ctx, - r->in.buffer, r->in.buffer_size, + r->in.buffer, + r->in.offered, &sec_desc); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); -- cgit From 8b9f2abfcb956f3ad496cefcc9d8ced8eadf1470 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 9 Apr 2009 15:08:29 +0200 Subject: s3-svcctl: Fix invalid buffer memset in _svcctl_QueryServiceObjectSecurity(). Found by torture-test. Guenther --- source3/rpc_server/srv_svcctl_nt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 8ed308ad6b..350a5ca236 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -873,7 +873,6 @@ WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p, *r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 ); if ( *r->out.needed > r->in.offered) { - ZERO_STRUCTP( &r->out.buffer ); return WERR_INSUFFICIENT_BUFFER; } -- cgit From 76da89daaadc358c836817cf597a1ff1489a9029 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 9 Apr 2009 15:39:45 +0200 Subject: s3-svcctl: minor fix for _svcctl_EnumDependentServicesW(). Guenther --- source3/rpc_server/srv_svcctl_nt.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 350a5ca236..0b0ef83bee 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -546,6 +546,15 @@ WERROR _svcctl_EnumDependentServicesW(pipes_struct *p, if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) ) return WERR_ACCESS_DENIED; + switch (r->in.state) { + case SERVICE_STATE_ACTIVE: + case SERVICE_STATE_INACTIVE: + case SERVICE_STATE_ALL: + break; + default: + return WERR_INVALID_PARAM; + } + /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ /* this is done in the autogenerated server already - gd */ -- cgit From ade9ef19835b6464eeddd351a165eb4b9bf2366c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Apr 2009 00:00:44 +0200 Subject: s3-rpcclient: allow to set flags in cmd_ntsvcs_get_dev_list(). Guenther --- source3/rpcclient/cmd_ntsvcs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpcclient/cmd_ntsvcs.c b/source3/rpcclient/cmd_ntsvcs.c index eb620d06b2..a345cdc8bf 100644 --- a/source3/rpcclient/cmd_ntsvcs.c +++ b/source3/rpcclient/cmd_ntsvcs.c @@ -235,17 +235,21 @@ static WERROR cmd_ntsvcs_get_dev_list(struct rpc_pipe_client *cli, uint32_t length = 0; uint32_t flags = 0; - if (argc > 3) { - printf("usage: %s [length] [filter]\n", argv[0]); + if (argc > 4) { + printf("usage: %s [filter] [length] [flags]\n", argv[0]); return WERR_OK; } if (argc >= 2) { - length = atoi(argv[1]); + filter = argv[1]; } if (argc >= 3) { - filter = argv[2]; + length = atoi(argv[2]); + } + + if (argc >= 4) { + flags = atoi(argv[3]); } buffer = talloc(mem_ctx, uint16_t); -- cgit From b7caf138518028507809bd6d356ec53b1564f0a1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Apr 2009 00:43:55 +0200 Subject: s3-ntsvcs: fix _PNP_GetDeviceList and _PNP_GetDeviceListSize. Guenther --- source3/rpc_server/srv_ntsvcs_nt.c | 41 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_ntsvcs_nt.c b/source3/rpc_server/srv_ntsvcs_nt.c index 681c543c24..7b8dc93a6e 100644 --- a/source3/rpc_server/srv_ntsvcs_nt.c +++ b/source3/rpc_server/srv_ntsvcs_nt.c @@ -3,6 +3,7 @@ * RPC Pipe client / server routines * * Copyright (C) Gerald (Jerry) Carter 2005. + * Copyright (C) Guenther Deschner 2008,2009. * * 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 @@ -50,8 +51,9 @@ WERROR _PNP_GetDeviceListSize(pipes_struct *p, { char *devicepath; - if (!r->in.devicename) { - return WERR_ACCESS_DENIED; + if ((r->in.flags & CM_GETIDLIST_FILTER_SERVICE) && + (!r->in.devicename)) { + return WERR_CM_INVALID_POINTER; } if (!(devicepath = get_device_path(p->mem_ctx, r->in.devicename))) { @@ -74,13 +76,14 @@ WERROR _PNP_GetDeviceList(pipes_struct *p, { char *devicepath; uint32_t size = 0; + char **multi_sz = NULL; + size_t multi_sz_len; + uint16_t *multi_sz_buf; - DATA_BLOB blob; - struct lsa_StringLarge s; - enum ndr_err_code ndr_err; - - if ( !r->in.filter ) - return WERR_ACCESS_DENIED; + if ((r->in.flags & CM_GETIDLIST_FILTER_SERVICE) && + (!r->in.filter)) { + return WERR_CM_INVALID_POINTER; + } if (!(devicepath = get_device_path(p->mem_ctx, r->in.filter))) { return WERR_NOMEM; @@ -92,20 +95,24 @@ WERROR _PNP_GetDeviceList(pipes_struct *p, return WERR_CM_BUFFER_SMALL; } - s.string = r->in.filter; - - /* This has to be DOUBLE NULL terminated */ - ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, &s, - (ndr_push_flags_fn_t)ndr_push_lsa_StringLarge); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err)); + multi_sz = talloc_zero_array(p->mem_ctx, char *, 2); + if (!multi_sz) { + return WERR_NOMEM; } - r->out.buffer = (uint16_t *)talloc_memdup(p->mem_ctx, blob.data, blob.length); - if (!r->out.buffer) { + multi_sz[0] = devicepath; + + multi_sz_len = regval_build_multi_sz(multi_sz, &multi_sz_buf); + if (!multi_sz_len) { return WERR_NOMEM; } + if (*r->in.length < multi_sz_len/2) { + return WERR_CM_BUFFER_SMALL; + } + + memcpy(r->out.buffer, multi_sz_buf, multi_sz_len); + return WERR_OK; } -- cgit From f930f504e1d5e78d2f6f36cab9ce36dbeb34e955 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Apr 2009 00:44:36 +0200 Subject: s3-selftest: enable the RPC-NTSVCS torture test against Samba3. Guenther --- source3/script/tests/test_posix_s3.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 18e8ef75af..b3a66e1db7 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -40,7 +40,7 @@ raw="$raw RAW-SAMBA3ROOTDIRFID" rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC" rpc="$rpc RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC" rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME" -rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN" +rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN RPC-NTSVCS" # NOTE: to enable the UNIX-WHOAMI test, we need to change the default share # config to allow guest access. I'm not sure whether this would break other -- cgit