diff options
Diffstat (limited to 'source3/rpc_server')
-rw-r--r-- | source3/rpc_server/srv_eventlog.c | 119 | ||||
-rw-r--r-- | source3/rpc_server/srv_eventlog_lib.c | 606 | ||||
-rw-r--r-- | source3/rpc_server/srv_eventlog_nt.c | 382 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_hnd.c | 22 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 83 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 321 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 2 |
7 files changed, 800 insertions, 735 deletions
diff --git a/source3/rpc_server/srv_eventlog.c b/source3/rpc_server/srv_eventlog.c deleted file mode 100644 index 39e3115561..0000000000 --- a/source3/rpc_server/srv_eventlog.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Marcin Krzysztof Porwit 2005. - * Copyright (C) Gerald Carter 2005 - 2007 - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "includes.h" -#include "librpc/gen_ndr/srv_eventlog.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -static bool proxy_eventlog_call(pipes_struct *p, uint8 opnum) -{ - struct api_struct *fns; - int n_fns; - - eventlog_get_pipe_fns(&fns, &n_fns); - - if (opnum >= n_fns) - return False; - - if (fns[opnum].opnum != opnum) { - smb_panic("EVENTLOG function table not sorted\n"); - } - - return fns[opnum].fn(p); -} - -static bool api_eventlog_open_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_OPENEVENTLOGW); -} - -static bool api_eventlog_close_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call( p, NDR_EVENTLOG_CLOSEEVENTLOG ); -} - -static bool api_eventlog_get_num_records(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_GETNUMRECORDS); -} - -static bool api_eventlog_get_oldest_entry(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_GETOLDESTRECORD); -} - -static bool api_eventlog_read_eventlog(pipes_struct *p) -{ - EVENTLOG_Q_READ_EVENTLOG q_u; - EVENTLOG_R_READ_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if (!(eventlog_io_q_read_eventlog("", &q_u, data, 0))) { - DEBUG(0, ("eventlog_io_q_read_eventlog: unable to unmarshall EVENTLOG_Q_READ_EVENTLOG.\n")); - return False; - } - - r_u.status = _eventlog_read_eventlog(p, &q_u, &r_u); - - if (!(eventlog_io_r_read_eventlog("", &q_u, &r_u, rdata, 0))) { - DEBUG(0, ("eventlog_io_r_read_eventlog: unable to marshall EVENTLOG_R_READ_EVENTLOG.\n")); - return False; - } - - return True; -} - -static bool api_eventlog_clear_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_CLEAREVENTLOGW); -} - -/* - \pipe\eventlog commands -*/ -struct api_struct api_eventlog_cmds[] = -{ - {"EVENTLOG_OPENEVENTLOG", EVENTLOG_OPENEVENTLOG, api_eventlog_open_eventlog }, - {"EVENTLOG_CLOSEEVENTLOG", EVENTLOG_CLOSEEVENTLOG, api_eventlog_close_eventlog }, - {"EVENTLOG_GETNUMRECORDS", EVENTLOG_GETNUMRECORDS, api_eventlog_get_num_records }, - {"EVENTLOG_GETOLDESTENTRY", EVENTLOG_GETOLDESTENTRY, api_eventlog_get_oldest_entry }, - {"EVENTLOG_READEVENTLOG", EVENTLOG_READEVENTLOG, api_eventlog_read_eventlog }, - {"EVENTLOG_CLEAREVENTLOG", EVENTLOG_CLEAREVENTLOG, api_eventlog_clear_eventlog } -}; - -NTSTATUS rpc_eventlog2_init(void) -{ - return rpc_srv_register(SMB_RPC_INTERFACE_VERSION, - "eventlog", "eventlog", &ndr_table_eventlog, - api_eventlog_cmds, - sizeof(api_eventlog_cmds)/sizeof(struct api_struct)); -} - -void eventlog2_get_pipe_fns(struct api_struct **fns, int *n_fns) -{ - *fns = api_eventlog_cmds; - *n_fns = sizeof(api_eventlog_cmds) / sizeof(struct api_struct); -} diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c index 8cbb319e9b..57b3be43ad 100644 --- a/source3/rpc_server/srv_eventlog_lib.c +++ b/source3/rpc_server/srv_eventlog_lib.c @@ -4,6 +4,7 @@ * 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 @@ -269,7 +270,7 @@ bool prune_eventlog( TDB_CONTEXT * tdb ) /******************************************************************** ********************************************************************/ -bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) +static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) { int calcd_size; int MaxSize, Retention; @@ -312,7 +313,7 @@ bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) /******************************************************************* *******************************************************************/ -ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) +ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only ) { TDB_CONTEXT *tdb = NULL; uint32_t vers_id; @@ -322,6 +323,13 @@ ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) 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 ) { @@ -363,7 +371,7 @@ ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) if ( !force_clear ) { - tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 ); + 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 ); @@ -437,148 +445,6 @@ int elog_close_tdb( ELOG_TDB *etdb, bool force_close ) return 0; } - -/******************************************************************* - 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 -*******************************************************************/ - -#define MARGIN 512 - -int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) -{ - int32 next_record; - uint8 *packed_ee; - TALLOC_CTX *mem_ctx = NULL; - TDB_DATA kbuf, ebuf; - uint32_t n_packed; - - if ( !ee ) - return 0; - - mem_ctx = talloc_init( "write_eventlog_tdb" ); - - if ( mem_ctx == NULL ) - return 0; - - /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */ - if ( ee->record.time_generated == 0 ) - return 0; - - /* todo - check for sanity in next_record */ - - fixup_eventlog_entry( ee ); - - if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) { - DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) ); - talloc_destroy( mem_ctx ); - return 0; - } - - /* alloc mem for the packed version */ - packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN ); - if ( !packed_ee ) { - talloc_destroy( mem_ctx ); - return 0; - } - - /* need to read the record number and insert it into the entry here */ - - /* lock */ - tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 ); - /* read */ - next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); - - n_packed = - tdb_pack( (uint8 *)packed_ee, ee->record.length + MARGIN, - "ddddddwwwwddddddBBdBBBd", ee->record.length, - ee->record.reserved1, next_record, - ee->record.time_generated, ee->record.time_written, - ee->record.event_id, ee->record.event_type, - ee->record.num_strings, ee->record.event_category, - ee->record.reserved2, - ee->record.closing_record_number, - ee->record.string_offset, - ee->record.user_sid_length, - ee->record.user_sid_offset, ee->record.data_length, - ee->record.data_offset, - ee->data_record.source_name_len, - ee->data_record.source_name, - ee->data_record.computer_name_len, - ee->data_record.computer_name, - ee->data_record.sid_padding, - ee->record.user_sid_length, ee->data_record.sid, - ee->data_record.strings_len, - ee->data_record.strings, - ee->data_record.user_data_len, - ee->data_record.user_data, - ee->data_record.data_padding ); - - /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */ - - /* increment the record count */ - - kbuf.dsize = sizeof( int32 ); - kbuf.dptr = (uint8 * ) & next_record; - - ebuf.dsize = n_packed; - ebuf.dptr = (uint8 *)packed_ee; - - if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) { - /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */ - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - talloc_destroy( mem_ctx ); - return 0; - } - next_record++; - tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record ); - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - talloc_destroy( mem_ctx ); - return ( next_record - 1 ); -} - -/******************************************************************* - calculate the correct fields etc for an eventlog entry -*******************************************************************/ - -void fixup_eventlog_entry( Eventlog_entry * ee ) -{ - /* fix up the eventlog entry structure as necessary */ - - ee->data_record.sid_padding = - ( ( 4 - - ( ( ee->data_record.source_name_len + - ee->data_record.computer_name_len ) % 4 ) ) % 4 ); - ee->data_record.data_padding = - ( 4 - - ( ( ee->data_record.strings_len + - ee->data_record.user_data_len ) % 4 ) ) % 4; - ee->record.length = sizeof( Eventlog_record ); - ee->record.length += ee->data_record.source_name_len; - ee->record.length += ee->data_record.computer_name_len; - if ( ee->record.user_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 */ - ee->data_record.data_padding += ee->data_record.sid_padding; - ee->data_record.sid_padding = 0; - } - /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */ - /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */ - - ee->record.length += ee->data_record.sid_padding; - ee->record.length += ee->record.user_sid_length; - ee->record.length += ee->data_record.strings_len; - ee->record.length += ee->data_record.user_data_len; - ee->record.length += ee->data_record.data_padding; - /* need another copy of length at the end of the data */ - ee->record.length += sizeof( ee->record.length ); -} - /******************************************************************** 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 @@ -587,9 +453,8 @@ void fixup_eventlog_entry( Eventlog_entry * ee ) going in. ********************************************************************/ -bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) +bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor ) { - TALLOC_CTX *ctx = talloc_tos(); char *start = NULL, *stop = NULL; start = line; @@ -609,32 +474,32 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) if ( 0 == strncmp( start, "LEN", stop - start ) ) { /* This will get recomputed later anyway -- probably not necessary */ - entry->record.length = atoi( stop + 1 ); + 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->record.reserved1 = atoi( stop + 1 ); + entry->reserved = talloc_strdup(mem_ctx, "eLfL"); } else if ( 0 == strncmp( start, "RCN", stop - start ) ) { - entry->record.record_number = atoi( stop + 1 ); + entry->record_number = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "TMG", stop - start ) ) { - entry->record.time_generated = atoi( stop + 1 ); + entry->time_generated = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "TMW", stop - start ) ) { - entry->record.time_written = atoi( stop + 1 ); + entry->time_written = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "EID", stop - start ) ) { - entry->record.event_id = atoi( stop + 1 ); + entry->event_id = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "ETP", stop - start ) ) { if ( strstr( start, "ERROR" ) ) { - entry->record.event_type = EVENTLOG_ERROR_TYPE; + entry->event_type = EVENTLOG_ERROR_TYPE; } else if ( strstr( start, "WARNING" ) ) { - entry->record.event_type = EVENTLOG_WARNING_TYPE; + entry->event_type = EVENTLOG_WARNING_TYPE; } else if ( strstr( start, "INFO" ) ) { - entry->record.event_type = EVENTLOG_INFORMATION_TYPE; + entry->event_type = EVENTLOG_INFORMATION_TYPE; } else if ( strstr( start, "AUDIT_SUCCESS" ) ) { - entry->record.event_type = EVENTLOG_AUDIT_SUCCESS; + entry->event_type = EVENTLOG_AUDIT_SUCCESS; } else if ( strstr( start, "AUDIT_FAILURE" ) ) { - entry->record.event_type = EVENTLOG_AUDIT_FAILURE; + entry->event_type = EVENTLOG_AUDIT_FAILURE; } else if ( strstr( start, "SUCCESS" ) ) { - entry->record.event_type = EVENTLOG_SUCCESS; + entry->event_type = EVENTLOG_SUCCESS; } else { /* some other eventlog type -- currently not defined in MSDN docs, so error out */ return False; @@ -644,27 +509,26 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) /* else if(0 == strncmp(start, "NST", stop - start)) { - entry->record.num_strings = atoi(stop + 1); + entry->num_of_strings = atoi(stop + 1); } */ else if ( 0 == strncmp( start, "ECT", stop - start ) ) { - entry->record.event_category = atoi( stop + 1 ); + entry->event_category = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "RS2", stop - start ) ) { - entry->record.reserved2 = atoi( stop + 1 ); + entry->reserved_flags = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "CRN", stop - start ) ) { - entry->record.closing_record_number = atoi( stop + 1 ); + entry->closing_record_number = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "USL", stop - start ) ) { - entry->record.user_sid_length = atoi( stop + 1 ); + entry->sid_length = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "SRC", stop - start ) ) { stop++; while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.source_name_len = rpcstr_push_talloc(ctx, - &entry->data_record.source_name, - stop); - if (entry->data_record.source_name_len == (uint32_t)-1 || - entry->data_record.source_name == NULL) { + 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 ) ) { @@ -672,54 +536,43 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.computer_name_len = rpcstr_push_talloc(ctx, - &entry->data_record.computer_name, - stop); - if (entry->data_record.computer_name_len == (uint32_t)-1 || - entry->data_record.computer_name == NULL) { + 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->record.user_sid_length = rpcstr_push_talloc(ctx, - &entry->data_record.sid, + entry->sid_length = rpcstr_push_talloc(mem_ctx, + &dummy, stop); - if (entry->record.user_sid_length == (uint32_t)-1 || - entry->data_record.sid == NULL) { + entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length); + if (entry->sid_length == (uint32_t)-1 || + entry->sid.data == NULL) { return false; } } else if ( 0 == strncmp( start, "STR", stop - start ) ) { - smb_ucs2_t *temp = NULL; size_t tmp_len; - uint32_t old_len; /* skip past initial ":" */ stop++; /* now skip any other leading whitespace */ while ( isspace(stop[0])) { stop++; } - tmp_len = rpcstr_push_talloc(ctx, - &temp, - stop); - if (tmp_len == (size_t)-1 || !temp) { + tmp_len = strlen_m_term(stop); + if (tmp_len == (size_t)-1) { return false; } - old_len = entry->data_record.strings_len; - entry->data_record.strings = (smb_ucs2_t *)TALLOC_REALLOC_ARRAY(ctx, - entry->data_record.strings, - char, - old_len + tmp_len); - if (!entry->data_record.strings) { + if (!add_string_to_array(mem_ctx, stop, &entry->strings, + (int *)&entry->num_of_strings)) { return false; } - memcpy(((char *)entry->data_record.strings) + old_len, - temp, - tmp_len); - entry->data_record.strings_len += tmp_len; - entry->record.num_strings++; + entry->strings_len += tmp_len; } else if ( 0 == strncmp( start, "DAT", stop - start ) ) { /* skip past initial ":" */ stop++; @@ -727,10 +580,9 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.user_data_len = strlen(stop); - entry->data_record.user_data = talloc_strdup(ctx, - stop); - if (!entry->data_record.user_data) { + entry->data_length = strlen_m(stop); + entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length); + if (!entry->data.data) { return false; } } else { @@ -742,3 +594,359 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) } 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, + &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_nt.c b/source3/rpc_server/srv_eventlog_nt.c index a687025ba6..697457888e 100644 --- a/source3/rpc_server/srv_eventlog_nt.c +++ b/source3/rpc_server/srv_eventlog_nt.c @@ -4,6 +4,7 @@ * 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 @@ -194,7 +195,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn in a single process */ become_root(); - elog->etdb = elog_open_tdb( elog->logname, False ); + elog->etdb = elog_open_tdb( elog->logname, False, False ); unbecome_root(); if ( !elog->etdb ) { @@ -214,7 +215,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn } become_root(); - elog->etdb = elog_open_tdb( elog->logname, False ); + elog->etdb = elog_open_tdb( elog->logname, False, False ); unbecome_root(); } @@ -276,140 +277,6 @@ static int elog_size( EVENTLOG_INFO *info ) } /******************************************************************** - For the given tdb, get the next eventlog record into the passed - Eventlog_entry. returns NULL if it can't get the record for some reason. - ********************************************************************/ - -static Eventlog_entry *get_eventlog_record(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - int recno) -{ - Eventlog_entry *ee = NULL; - TDB_DATA ret, key; - - int32_t srecno; - int32_t reclen; - int len; - - char *wpsource = NULL; - char *wpcomputer = NULL; - char *wpsid = NULL; - char *wpstrs = NULL; - char *puserdata = NULL; - - key.dsize = sizeof(int32_t); - - srecno = recno; - key.dptr = (unsigned char *)&srecno; - - ret = tdb_fetch( tdb, key ); - - if ( ret.dsize == 0 ) { - DEBUG( 8, - ( "Can't find a record for the key, record %d\n", - recno ) ); - return NULL; - } - - len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen ); - - DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) ); - - if ( !len ) - return NULL; - - ee = TALLOC_ARRAY(mem_ctx, Eventlog_entry, 1); - if (!ee) { - return NULL; - } - ZERO_STRUCTP(ee); - - len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd", - &ee->record.length, &ee->record.reserved1, - &ee->record.record_number, - &ee->record.time_generated, - &ee->record.time_written, &ee->record.event_id, - &ee->record.event_type, &ee->record.num_strings, - &ee->record.event_category, &ee->record.reserved2, - &ee->record.closing_record_number, - &ee->record.string_offset, - &ee->record.user_sid_length, - &ee->record.user_sid_offset, - &ee->record.data_length, &ee->record.data_offset, - &ee->data_record.source_name_len, &wpsource, - &ee->data_record.computer_name_len, &wpcomputer, - &ee->data_record.sid_padding, - &ee->record.user_sid_length, &wpsid, - &ee->data_record.strings_len, &wpstrs, - &ee->data_record.user_data_len, &puserdata, - &ee->data_record.data_padding ); - DEBUG( 10, - ( "Read record %d, len in tdb was %d\n", - ee->record.record_number, len ) ); - - /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff - into it's 2nd argment for 'B' */ - - if (wpcomputer) { - ee->data_record.computer_name = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpcomputer, ee->data_record.computer_name_len); - if (!ee->data_record.computer_name) { - TALLOC_FREE(ee); - goto out; - } - } - if (wpsource) { - ee->data_record.source_name = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpsource, ee->data_record.source_name_len); - if (!ee->data_record.source_name) { - TALLOC_FREE(ee); - goto out; - } - } - - if (wpsid) { - ee->data_record.sid = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpsid, ee->record.user_sid_length); - if (!ee->data_record.sid) { - TALLOC_FREE(ee); - goto out; - } - } - if (wpstrs) { - ee->data_record.strings = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpstrs, ee->data_record.strings_len); - if (!ee->data_record.strings) { - TALLOC_FREE(ee); - goto out; - } - } - - if (puserdata) { - ee->data_record.user_data = (char *)TALLOC_MEMDUP( - ee, puserdata, ee->data_record.user_data_len); - if (!ee->data_record.user_data) { - TALLOC_FREE(ee); - goto out; - } - } - - out: - - SAFE_FREE(wpcomputer); - SAFE_FREE(wpsource); - SAFE_FREE(wpsid); - SAFE_FREE(wpstrs); - SAFE_FREE(puserdata); - - DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) ); - DEBUG( 10, - ( "get_eventlog_record: computer_name %d is ", - ee->data_record.computer_name_len ) ); - SAFE_FREE(ret.dptr); - return ee; -} - -/******************************************************************** note that this can only be called AFTER the table is constructed, since it uses the table to find the tdb handle ********************************************************************/ @@ -484,124 +351,6 @@ done: } /******************************************************************** - ********************************************************************/ - -static Eventlog_entry *read_package_entry( TALLOC_CTX *mem_ctx, - Eventlog_entry * entry ) -{ - uint8 *offset; - Eventlog_entry *ee_new = NULL; - - ee_new = TALLOC_ZERO_ARRAY(mem_ctx, Eventlog_entry, 1 ); - if ( ee_new == NULL ) { - return NULL; - } - - entry->data_record.sid_padding = - ( ( 4 - - ( ( entry->data_record.source_name_len + - entry->data_record.computer_name_len ) % 4 ) ) % 4 ); - entry->data_record.data_padding = - ( 4 - - ( ( entry->data_record.strings_len + - entry->data_record.user_data_len ) % 4 ) ) % 4; - entry->record.length = sizeof( Eventlog_record ); - entry->record.length += entry->data_record.source_name_len; - entry->record.length += entry->data_record.computer_name_len; - if ( entry->record.user_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 */ - entry->data_record.data_padding += - entry->data_record.sid_padding; - entry->data_record.sid_padding = 0; - } - DEBUG( 10, - ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) ); - DEBUG( 10, - ( "data_padding is [%d].\n", - entry->data_record.data_padding ) ); - - entry->record.length += entry->data_record.sid_padding; - entry->record.length += entry->record.user_sid_length; - entry->record.length += entry->data_record.strings_len; - entry->record.length += entry->data_record.user_data_len; - entry->record.length += entry->data_record.data_padding; - /* need another copy of length at the end of the data */ - entry->record.length += sizeof( entry->record.length ); - DEBUG( 10, - ( "entry->record.length is [%d].\n", entry->record.length ) ); - entry->data = - TALLOC_ZERO_ARRAY(mem_ctx, uint8_t, - entry->record.length - - sizeof( Eventlog_record ) - - sizeof( entry->record.length )); - if ( entry->data == NULL ) { - return NULL; - } - offset = entry->data; - memcpy( offset, entry->data_record.source_name, - entry->data_record.source_name_len ); - offset += entry->data_record.source_name_len; - memcpy( offset, entry->data_record.computer_name, - entry->data_record.computer_name_len ); - offset += entry->data_record.computer_name_len; - /* SID needs to be DWORD-aligned */ - offset += entry->data_record.sid_padding; - entry->record.user_sid_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.sid, - entry->record.user_sid_length ); - offset += entry->record.user_sid_length; - /* Now do the strings */ - entry->record.string_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.strings, - entry->data_record.strings_len ); - offset += entry->data_record.strings_len; - /* Now do the data */ - entry->record.data_length = entry->data_record.user_data_len; - entry->record.data_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.user_data, - entry->data_record.user_data_len ); - offset += entry->data_record.user_data_len; - - memcpy( &( ee_new->record ), &entry->record, - sizeof( Eventlog_record ) ); - memcpy( &( ee_new->data_record ), &entry->data_record, - sizeof( Eventlog_data_record ) ); - ee_new->data = entry->data; - - return ee_new; -} - -/******************************************************************** - ********************************************************************/ - -static bool add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u, - Eventlog_entry * ee_new ) -{ - Eventlog_entry *insert_point; - - insert_point = r_u->entry; - - if ( NULL == insert_point ) { - r_u->entry = ee_new; - ee_new->next = NULL; - } else { - while ( ( NULL != insert_point->next ) ) { - insert_point = insert_point->next; - } - ee_new->next = NULL; - insert_point->next = ee_new; - } - r_u->num_records++; - r_u->num_bytes_in_resp += ee_new->record.length; - - return True; -} - -/******************************************************************** _eventlog_OpenEventLogW ********************************************************************/ @@ -677,7 +426,7 @@ NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p, elog_close_tdb( info->etdb, True ); become_root(); - info->etdb = elog_open_tdb( info->logname, True ); + info->etdb = elog_open_tdb( info->logname, True, False ); unbecome_root(); if ( !info->etdb ) @@ -706,98 +455,117 @@ NTSTATUS _eventlog_CloseEventLog(pipes_struct * p, } /******************************************************************** + _eventlog_ReadEventLogW ********************************************************************/ -NTSTATUS _eventlog_read_eventlog( pipes_struct * p, - EVENTLOG_Q_READ_EVENTLOG * q_u, - EVENTLOG_R_READ_EVENTLOG * r_u ) +NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, + struct eventlog_ReadEventLogW *r) { - EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); - Eventlog_entry *entry = NULL, *ee_new = NULL; - uint32 num_records_read = 0; + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle ); + uint32_t num_records_read = 0; int bytes_left, record_number; - uint32 elog_read_type, elog_read_dir; + uint32_t elog_read_type, elog_read_dir; - if (info == NULL) { + if (!info) { return NT_STATUS_INVALID_HANDLE; } - info->flags = q_u->flags; + info->flags = r->in.flags; + bytes_left = r->in.number_of_bytes; - bytes_left = q_u->max_read_size; - - if ( !info->etdb ) + if (!info->etdb) { return NT_STATUS_ACCESS_DENIED; + } /* check for valid flags. Can't use the sequential and seek flags together */ - elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); - elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); + elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); + elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); - if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) - || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) ) + if (r->in.flags == 0 || + elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) || + elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ)) { - DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags)); + DEBUG(3,("_eventlog_ReadEventLogW: " + "Invalid flags [0x%08x] for ReadEventLog\n", + r->in.flags)); return NT_STATUS_INVALID_PARAMETER; } /* a sequential read should ignore the offset */ - if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ ) + if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) { record_number = info->current_record; - else - record_number = q_u->offset; + } else { + record_number = r->in.offset; + } + + if (r->in.number_of_bytes == 0) { + struct EVENTLOGRECORD *e; + e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), + record_number); + if (!e) { + return NT_STATUS_END_OF_FILE; + } + *r->out.real_size = e->Length; + return NT_STATUS_BUFFER_TOO_SMALL; + } - while ( bytes_left > 0 ) { + while (bytes_left > 0) { - /* assume that when the record fetch fails, that we are done */ + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct EVENTLOGRECORD *e; - entry = get_eventlog_record (p->mem_ctx, ELOG_TDB_CTX(info->etdb), record_number); - if (!entry) { + e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), + record_number); + if (!e) { break; } - DEBUG( 8, ( "Retrieved record %d\n", record_number ) ); - - /* Now see if there is enough room to add */ - - if ( !(ee_new = read_package_entry( p->mem_ctx, entry )) ) - return NT_STATUS_NO_MEMORY; + ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, e, + (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } - if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) { - r_u->bytes_in_next_record = ee_new->record.length; + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGRECORD, e); + } - /* response would be too big to fit in client-size buffer */ + if (blob.length > r->in.number_of_bytes) { + *r->out.real_size = blob.length; + return NT_STATUS_BUFFER_TOO_SMALL; + } - bytes_left = 0; + if (*r->out.sent_size + blob.length > r->in.number_of_bytes) { break; } - add_record_to_resp( r_u, ee_new ); - bytes_left -= ee_new->record.length; - TALLOC_FREE(entry); - num_records_read = r_u->num_records - num_records_read; + bytes_left -= blob.length; - DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total " - "of [%d] records using [%d] bytes out of a max of [%d].\n", - num_records_read, r_u->num_records, - r_u->num_bytes_in_resp, - q_u->max_read_size ) ); - - if ( info->flags & EVENTLOG_FORWARDS_READ ) + if (info->flags & EVENTLOG_FORWARDS_READ) { record_number++; - else + } else { record_number--; + } /* update the eventlog record pointer */ info->current_record = record_number; + + memcpy(&r->out.data[*(r->out.sent_size)], + blob.data, blob.length); + *(r->out.sent_size) += blob.length; + + num_records_read++; } - /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to - say when there are no more records */ + if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) { + return NT_STATUS_END_OF_FILE; + } - return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL); + return NT_STATUS_OK; } /******************************************************************** @@ -872,12 +640,6 @@ NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBack return NT_STATUS_NOT_IMPLEMENTED; } -NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, struct eventlog_ReadEventLogW *r) -{ - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; -} - NTSTATUS _eventlog_ReportEventW(pipes_struct *p, struct eventlog_ReportEventW *r) { p->rng_fault_state = True; diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index 5f7c8d9f1a..2779b8aa18 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -34,9 +34,10 @@ pipe is open. JRA. ****************************************************************************/ -static bool is_samr_lsa_pipe(const char *pipe_name) +static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax) { - return (strstr(pipe_name, "samr") || strstr(pipe_name, "lsa")); + return (ndr_syntax_id_equal(syntax, &ndr_table_samr.syntax_id) + || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id)); } /**************************************************************************** @@ -44,7 +45,7 @@ static bool is_samr_lsa_pipe(const char *pipe_name) pipes of the same name. ****************************************************************************/ -bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) +bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax) { pipes_struct *plist; struct handle_list *hl; @@ -52,11 +53,11 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) { - if (strequal(plist->name, pipe_name)) { + if (ndr_syntax_id_equal(syntax, &plist->syntax)) { break; } - if (is_samr_lsa_pipe(plist->name) - && is_samr_lsa_pipe(pipe_name)) { + if (is_samr_lsa_pipe(&plist->syntax) + && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) @@ -80,7 +81,8 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) } ZERO_STRUCTP(hl); - DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name )); + DEBUG(10,("init_pipe_handles: created handle list for " + "pipe %s\n", get_pipe_name_from_iface(syntax))); } /* @@ -96,7 +98,8 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) p->pipe_handles = hl; DEBUG(10,("init_pipe_handles: pipe_handles ref count = %lu for pipe %s\n", - (unsigned long)p->pipe_handles->pipe_ref_count, pipe_name )); + (unsigned long)p->pipe_handles->pipe_ref_count, + get_pipe_name_from_iface(syntax))); return True; } @@ -242,7 +245,8 @@ void close_policy_by_pipe(pipes_struct *p) p->pipe_handles->count = 0; SAFE_FREE(p->pipe_handles); - DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name )); + DEBUG(10,("close_policy_by_pipe: deleted handle list for " + "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); } } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 343342a06c..924226bc4f 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -610,7 +610,8 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; bool ret; - DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n", p->name)); + DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n", + get_pipe_name_from_iface(&p->syntax))); ZERO_STRUCT(reply); @@ -634,7 +635,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested " "but client declined signing.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); return False; } } @@ -642,7 +643,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested " "but client declined sealing.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); return False; } } @@ -962,14 +963,14 @@ bool check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, int i=0; struct pipe_rpc_fns *context_fns; - DEBUG(3,("check_bind_req for %s\n", p->name)); + DEBUG(3,("check_bind_req for %s\n", + get_pipe_name_from_iface(&p->syntax))); /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ for (i=0; i<rpc_lookup_size; i++) { DEBUGADD(10, ("checking %s\n", rpc_lookup[i].pipe.clnt)); - if (strequal(rpc_lookup[i].pipe.clnt, p->name) - && ndr_syntax_id_equal( + if (ndr_syntax_id_equal( abstract, &rpc_lookup[i].rpc_interface) && ndr_syntax_id_equal( transfer, &ndr_transfer_syntax)) { @@ -1056,7 +1057,7 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv, * @param[in] cli_filename The pipe name requested by the client * @result Do we want to serve this? */ -bool is_known_pipename(const char *cli_filename) +bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax) { const char *pipename = cli_filename; int i; @@ -1076,6 +1077,7 @@ bool is_known_pipename(const char *cli_filename) for (i=0; i<rpc_lookup_size; i++) { if (strequal(pipename, rpc_lookup[i].pipe.clnt)) { + *syntax = rpc_lookup[i].rpc_interface; return true; } } @@ -1145,7 +1147,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_ } DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); - if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || USE_KERBEROS_KEYTAB) ) { bool ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth); data_blob_free(&secblob); data_blob_free(&blob); @@ -1530,7 +1532,8 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { - DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound pipe %s.\n", p->pipe_srv_name)); + DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound " + "pipe %s.\n", get_pipe_name_from_iface(&p->syntax))); return setup_bind_nak(p); } @@ -1589,16 +1592,20 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) &hdr_rb.rpc_context[0].abstract)) { DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->name, rpc_lookup[i].pipe.clnt); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); break; } } if (i == rpc_lookup_size) { - if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { + NTSTATUS status; + + status = smb_probe_module( + "rpc", get_pipe_name_from_iface( + &hdr_rb.rpc_context[0].abstract)); + + if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", - p->name )); + get_pipe_name_from_iface(&hdr_rb.rpc_context[0].abstract))); prs_mem_free(&outgoing_rpc); prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); @@ -1607,23 +1614,26 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) } for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { + if (strequal(rpc_lookup[i].pipe.clnt, + get_pipe_name_from_iface(&p->syntax))) { DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); break; } } if (i == rpc_lookup_size) { - DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); + DEBUG(0, ("module %s doesn't provide functions for " + "pipe %s!\n", + get_pipe_name_from_iface(&p->syntax), + get_pipe_name_from_iface(&p->syntax))); goto err_exit; } } /* name has to be \PIPE\xxxxx */ fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, p->pipe_srv_name); + fstrcat(ack_pipe_name, rpc_lookup[i].pipe.srv); DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); @@ -2233,7 +2243,7 @@ void free_pipe_rpc_context( PIPE_RPC_FNS *list ) return; } -static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, +static bool api_rpcTNP(pipes_struct *p, const struct api_struct *api_rpc_cmds, int n_cmds); /**************************************************************************** @@ -2258,7 +2268,8 @@ bool api_pipe_request(pipes_struct *p) changed_user = True; } - DEBUG(5, ("Requested \\PIPE\\%s\n", p->name)); + DEBUG(5, ("Requested \\PIPE\\%s\n", + get_pipe_name_from_iface(&p->syntax))); /* get the set of RPC functions for this context */ @@ -2266,12 +2277,13 @@ bool api_pipe_request(pipes_struct *p) if ( pipe_fns ) { TALLOC_CTX *frame = talloc_stackframe(); - ret = api_rpcTNP(p, p->name, pipe_fns->cmds, pipe_fns->n_cmds); + ret = api_rpcTNP(p, pipe_fns->cmds, pipe_fns->n_cmds); TALLOC_FREE(frame); } else { DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n", - p->hdr_req.context_id, p->name)); + p->hdr_req.context_id, + get_pipe_name_from_iface(&p->syntax))); } if (changed_user) { @@ -2285,18 +2297,22 @@ bool api_pipe_request(pipes_struct *p) Calls the underlying RPC function for a named pipe. ********************************************************************/ -static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, +static bool api_rpcTNP(pipes_struct *p, const struct api_struct *api_rpc_cmds, int n_cmds) { int fn_num; - fstring name; uint32 offset1, offset2; /* interpret the command */ - DEBUG(4,("api_rpcTNP: %s op 0x%x - ", rpc_name, p->hdr_req.opnum)); + DEBUG(4,("api_rpcTNP: %s op 0x%x - ", + get_pipe_name_from_iface(&p->syntax), p->hdr_req.opnum)); - slprintf(name, sizeof(name)-1, "in_%s", rpc_name); - prs_dump(name, p->hdr_req.opnum, &p->in_data.data); + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "in_%s", + get_pipe_name_from_iface(&p->syntax)); + prs_dump(name, p->hdr_req.opnum, &p->in_data.data); + } for (fn_num = 0; fn_num < n_cmds; fn_num++) { if (api_rpc_cmds[fn_num].opnum == p->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL) { @@ -2322,7 +2338,9 @@ static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, fn_num, api_rpc_cmds[fn_num].fn)); /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { - DEBUG(0,("api_rpcTNP: %s: %s failed.\n", rpc_name, api_rpc_cmds[fn_num].name)); + DEBUG(0,("api_rpcTNP: %s: %s failed.\n", + get_pipe_name_from_iface(&p->syntax), + api_rpc_cmds[fn_num].name)); prs_mem_free(&p->out_data.rdata); return False; } @@ -2341,13 +2359,18 @@ static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, return True; } - slprintf(name, sizeof(name)-1, "out_%s", rpc_name); offset2 = prs_offset(&p->out_data.rdata); prs_set_offset(&p->out_data.rdata, offset1); - prs_dump(name, p->hdr_req.opnum, &p->out_data.rdata); + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "out_%s", + get_pipe_name_from_iface(&p->syntax)); + prs_dump(name, p->hdr_req.opnum, &p->out_data.rdata); + } prs_set_offset(&p->out_data.rdata, offset2); - DEBUG(5,("api_rpcTNP: called %s successfully\n", rpc_name)); + DEBUG(5,("api_rpcTNP: called %s successfully\n", + get_pipe_name_from_iface(&p->syntax))); /* Check for buffer underflow in rpc parsing */ diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 0753476230..4cbe8d67a3 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -90,13 +90,14 @@ static bool pipe_init_outgoing_data(pipes_struct *p) ****************************************************************************/ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, - const char *pipe_name, + const struct ndr_syntax_id *syntax, const char *client_address, struct auth_serversupplied_info *server_info) { pipes_struct *p; - DEBUG(4,("Create pipe requested %s\n", pipe_name)); + DEBUG(4,("Create pipe requested %s\n", + get_pipe_name_from_iface(syntax))); p = TALLOC_ZERO_P(mem_ctx, struct pipes_struct); @@ -105,13 +106,15 @@ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, return NULL; } - if ((p->mem_ctx = talloc_init("pipe %s %p", pipe_name, p)) == NULL) { + if ((p->mem_ctx = talloc_init("pipe %s %p", + get_pipe_name_from_iface(syntax), + p)) == NULL) { DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n")); TALLOC_FREE(p); return NULL; } - if (!init_pipe_handle_list(p, pipe_name)) { + if (!init_pipe_handle_list(p, syntax)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); talloc_destroy(p->mem_ctx); TALLOC_FREE(p); @@ -152,11 +155,11 @@ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, * Initialize the outgoing RPC data buffer with no memory. */ prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL); - - fstrcpy(p->name, pipe_name); - + + p->syntax = *syntax; + DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n", - pipe_name, pipes_open)); + get_pipe_name_from_iface(syntax), pipes_open)); talloc_set_destructor(p, close_internal_rpc_pipe_hnd); @@ -174,7 +177,7 @@ static void set_incoming_fault(pipes_struct *p) p->in_data.pdu_received_len = 0; p->fault_state = True; DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); } /**************************************************************************** @@ -324,7 +327,8 @@ static void free_pipe_context(pipes_struct *p) "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) )); talloc_free_children(p->mem_ctx); } else { - p->mem_ctx = talloc_init("pipe %s %p", p->name, p); + p->mem_ctx = talloc_init( + "pipe %s %p", get_pipe_name_from_iface(&p->syntax), p); if (p->mem_ctx == NULL) { p->fault_state = True; } @@ -492,7 +496,7 @@ static void process_complete_pdu(pipes_struct *p) if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return; @@ -520,12 +524,13 @@ static void process_complete_pdu(pipes_struct *p) case RPC_PING: /* CL request - ignore... */ DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; case RPC_RESPONSE: /* No responses here. */ DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_FAULT: @@ -537,7 +542,8 @@ static void process_complete_pdu(pipes_struct *p) case RPC_FACK: case RPC_CANCEL_ACK: DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; case RPC_BIND: @@ -552,7 +558,8 @@ static void process_complete_pdu(pipes_struct *p) case RPC_BINDACK: case RPC_BINDNACK: DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; @@ -567,7 +574,7 @@ static void process_complete_pdu(pipes_struct *p) case RPC_ALTCONTRESP: DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_AUTH3: @@ -581,7 +588,7 @@ static void process_complete_pdu(pipes_struct *p) case RPC_SHUTDOWN: DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_CO_CANCEL: @@ -619,7 +626,8 @@ static void process_complete_pdu(pipes_struct *p) prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN); if (!reply) { - DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name)); + DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " + "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); prs_mem_free(&rpc_in); @@ -773,7 +781,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_ return -1; } - DEBUG(6,(" name: %s len: %u\n", p->name, (unsigned int)n)); + DEBUG(6,(" name: %s len: %u\n", get_pipe_name_from_iface(&p->syntax), + (unsigned int)n)); /* * We cannot return more than one PDU length per @@ -787,8 +796,10 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_ */ if(n > RPC_MAX_PDU_FRAG_LEN) { - DEBUG(5,("read_from_pipe: too large read (%u) requested on \ -pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN )); + DEBUG(5,("read_from_pipe: too large read (%u) requested on " + "pipe %s. We can only service %d sized reads.\n", + (unsigned int)n, get_pipe_name_from_iface(&p->syntax), + RPC_MAX_PDU_FRAG_LEN )); n = RPC_MAX_PDU_FRAG_LEN; } @@ -803,9 +814,12 @@ pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_M if((pdu_remaining = p->out_data.current_pdu_len - p->out_data.current_pdu_sent) > 0) { data_returned = (ssize_t)MIN(n, pdu_remaining); - DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \ -returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, - (unsigned int)p->out_data.current_pdu_sent, (int)data_returned)); + DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " + "current_pdu_sent = %u returning %d bytes.\n", + get_pipe_name_from_iface(&p->syntax), + (unsigned int)p->out_data.current_pdu_len, + (unsigned int)p->out_data.current_pdu_sent, + (int)data_returned)); memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; @@ -817,9 +831,11 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, * may of course be zero if this is the first return fragment. */ - DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \ -= %u, prs_offset(&p->out_data.rdata) = %u.\n", - p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) )); + DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " + "= %u, prs_offset(&p->out_data.rdata) = %u.\n", + get_pipe_name_from_iface(&p->syntax), (int)p->fault_state, + (unsigned int)p->out_data.data_sent_length, + (unsigned int)prs_offset(&p->out_data.rdata) )); if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) { /* @@ -837,7 +853,8 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, */ if(!create_next_pdu(p)) { - DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", p->name)); + DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", + get_pipe_name_from_iface(&p->syntax))); return -1; } @@ -1086,13 +1103,14 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, handle->private_data = p; } else { struct pipes_struct *p; + struct ndr_syntax_id syntax; - if (!is_known_pipename(name)) { + if (!is_known_pipename(name, &syntax)) { TALLOC_FREE(handle); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - p = make_internal_rpc_pipe_p(handle, name, client_address, + p = make_internal_rpc_pipe_p(handle, &syntax, client_address, server_info); handle->type = FAKE_FILE_TYPE_NAMED_PIPE; @@ -1109,66 +1127,235 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, return NT_STATUS_OK; } -NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data, - size_t len, ssize_t *nwritten) +struct np_write_state { + ssize_t nwritten; +}; + +static void np_write_done(struct async_req *subreq); + +struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + const uint8_t *data, size_t len) { - DEBUG(6, ("np_write: len: %d\n", (int)len)); + struct async_req *result, *subreq; + struct np_write_state *state; + NTSTATUS status; + + DEBUG(6, ("np_write_send: len: %d\n", (int)len)); dump_data(50, data, len); - switch (handle->type) { - case FAKE_FILE_TYPE_NAMED_PIPE: { + if (!async_req_setup(mem_ctx, &result, &state, + struct np_write_state)) { + return NULL; + } + + if (len == 0) { + state->nwritten = 0; + status = NT_STATUS_OK; + goto post_status; + } + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) { struct pipes_struct *p = talloc_get_type_abort( handle->private_data, struct pipes_struct); - *nwritten = write_to_internal_pipe(p, (char *)data, len); - break; + + state->nwritten = write_to_internal_pipe(p, (char *)data, len); + + status = (state->nwritten >= 0) + ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + goto post_status; } - case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) { struct np_proxy_state *p = talloc_get_type_abort( handle->private_data, struct np_proxy_state); - *nwritten = write_data(p->fd, (char *)data, len); - break; + + state->nwritten = len; + + subreq = sendall_send(state, ev, p->fd, data, len, 0); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = np_write_done; + subreq->async.priv = result; + return result; } - default: - return NT_STATUS_INVALID_HANDLE; - break; + + status = NT_STATUS_INVALID_HANDLE; + post_status: + if (async_post_ntstatus(result, ev, status)) { + return result; } + fail: + TALLOC_FREE(result); + return NULL; +} + +static void np_write_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS np_write_recv(struct async_req *req, ssize_t *pnwritten) +{ + struct np_write_state *state = talloc_get_type_abort( + req->private_data, struct np_write_state); + NTSTATUS status; - return ((*nwritten) >= 0) - ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + if (async_req_is_nterror(req, &status)) { + return status; + } + *pnwritten = state->nwritten; + return NT_STATUS_OK; } -NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len, - ssize_t *nread, bool *is_data_outstanding) +struct np_read_state { + ssize_t nread; + bool is_data_outstanding; + int fd; +}; + +static void np_read_done(struct async_req *subreq); + +struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + uint8_t *data, size_t len) { - switch (handle->type) { - case FAKE_FILE_TYPE_NAMED_PIPE: { + struct async_req *result, *subreq; + struct np_read_state *state; + NTSTATUS status; + + if (!async_req_setup(mem_ctx, &result, &state, + struct np_read_state)) { + return NULL; + } + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) { struct pipes_struct *p = talloc_get_type_abort( handle->private_data, struct pipes_struct); - *nread = read_from_internal_pipe(p, (char *)data, len, - is_data_outstanding); - break; + + state->nread = read_from_internal_pipe( + p, (char *)data, len, &state->is_data_outstanding); + + status = (state->nread >= 0) + ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + goto post_status; } - case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) { struct np_proxy_state *p = talloc_get_type_abort( handle->private_data, struct np_proxy_state); - int available = 0; - *nread = sys_read(p->fd, (char *)data, len); + state->fd = p->fd; - /* - * We don't look at the ioctl result. We don't really care - * if there is data available, because this is racy anyway. - */ - ioctl(p->fd, FIONREAD, &available); - *is_data_outstanding = (available > 0); + subreq = async_recv(state, ev, p->fd, data, len, 0); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = np_read_done; + subreq->async.priv = result; + return result; + } + + status = NT_STATUS_INVALID_HANDLE; + post_status: + if (async_post_ntstatus(result, ev, status)) { + return result; + } + fail: + TALLOC_FREE(result); + return NULL; +} + +static void np_read_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct np_read_state *state = talloc_get_type_abort( + req->private_data, struct np_read_state); + ssize_t result; + int sys_errno; + int available = 0; + + result = async_syscall_result_ssize_t(subreq, &sys_errno); + if (result == -1) { + async_req_nterror(req, map_nt_error_from_unix(sys_errno)); + return; + } + if (result == 0) { + async_req_nterror(req, NT_STATUS_END_OF_FILE); + return; + } + + state->nread = result; - break; + /* + * We don't look at the ioctl result. We don't really care if there is + * data available, because this is racy anyway. + */ + ioctl(state->fd, FIONREAD, &available); + state->is_data_outstanding = (available > 0); + + async_req_done(req); +} + +NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread, + bool *is_data_outstanding) +{ + struct np_read_state *state = talloc_get_type_abort( + req->private_data, struct np_read_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + *nread = state->nread; + *is_data_outstanding = state->is_data_outstanding; + return NT_STATUS_OK; +} + +/** + * Create a new RPC client context which uses a local dispatch function. + */ +NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *abstract_syntax, + NTSTATUS (*dispatch) (struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const struct ndr_interface_table *table, + uint32_t opnum, void *r), + struct auth_serversupplied_info *serversupplied_info, + struct rpc_pipe_client **presult) +{ + struct rpc_pipe_client *result; + + result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; } - default: - return NT_STATUS_INVALID_HANDLE; - break; + + result->abstract_syntax = *abstract_syntax; + result->transfer_syntax = ndr_transfer_syntax; + result->dispatch = dispatch; + + result->pipes_struct = make_internal_rpc_pipe_p( + result, abstract_syntax, "", serversupplied_info); + if (result->pipes_struct == NULL) { + TALLOC_FREE(result); + return NT_STATUS_NO_MEMORY; } - return ((*nread) >= 0) - ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + result->max_xmit_frag = -1; + result->max_recv_frag = -1; + + *presult = result; + return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index ba2fe774b8..e61d343731 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1701,7 +1701,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, /* check smb.conf parameters and the the sec_desc */ - if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) { + if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) { DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n")); return WERR_ACCESS_DENIED; } |