rpc_server/srv_eventlog_nt.c

説明を見る。
00001 /* 
00002  *  Unix SMB/CIFS implementation.
00003  *  RPC Pipe client / server routines
00004  *  Copyright (C) Marcin Krzysztof Porwit    2005,
00005  *  Copyright (C) Brian Moran                2005,
00006  *  Copyright (C) Gerald (Jerry) Carter      2005.
00007  *  
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *  
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *  
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021  */
00022 
00023 #include "includes.h"
00024 
00025 #undef  DBGC_CLASS
00026 #define DBGC_CLASS DBGC_RPC_SRV
00027 
00028 typedef struct {
00029         char *logname;
00030         ELOG_TDB *etdb;
00031         uint32 current_record;
00032         uint32 num_records;
00033         uint32 oldest_entry;
00034         uint32 flags;
00035         uint32 access_granted;
00036 } EVENTLOG_INFO;
00037 
00038 /********************************************************************
00039  ********************************************************************/
00040 
00041 static void free_eventlog_info( void *ptr )
00042 {
00043         EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
00044         
00045         if ( elog->etdb )
00046                 elog_close_tdb( elog->etdb, False );
00047         
00048         TALLOC_FREE( elog );
00049 }
00050 
00051 /********************************************************************
00052  ********************************************************************/
00053 
00054 static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
00055                                                 POLICY_HND * handle )
00056 {
00057         EVENTLOG_INFO *info;
00058 
00059         if ( !find_policy_by_hnd( p, handle, (void **)(void *)&info ) ) {
00060                 DEBUG( 2,
00061                        ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
00062                 return NULL;
00063         }
00064 
00065         return info;
00066 }
00067 
00068 /********************************************************************
00069 ********************************************************************/
00070 
00071 static BOOL elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
00072 {
00073         char *tdbname = elog_tdbname( info->logname );
00074         SEC_DESC *sec_desc;
00075         BOOL ret;
00076         NTSTATUS ntstatus;
00077         
00078         if ( !tdbname ) 
00079                 return False;
00080         
00081         /* get the security descriptor for the file */
00082         
00083         sec_desc = get_nt_acl_no_snum( info, tdbname );
00084         SAFE_FREE( tdbname );
00085         
00086         if ( !sec_desc ) {
00087                 DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n", 
00088                         tdbname));
00089                 return False;
00090         }
00091         
00092         /* root free pass */
00093 
00094         if ( geteuid() == sec_initial_uid() ) {
00095                 DEBUG(5,("elog_check_access: using root's token\n"));
00096                 token = get_root_nt_token();
00097         }
00098 
00099         /* run the check, try for the max allowed */
00100         
00101         ret = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
00102                 &info->access_granted, &ntstatus );
00103                 
00104         if ( sec_desc )
00105                 TALLOC_FREE( sec_desc );
00106                 
00107         if ( !ret ) {
00108                 DEBUG(8,("elog_check_access: se_access_check() return %s\n",
00109                         nt_errstr( ntstatus)));
00110                 return False;
00111         }
00112         
00113         /* we have to have READ permission for a successful open */
00114         
00115         return ( info->access_granted & SA_RIGHT_FILE_READ_DATA );
00116 }
00117 
00118 /********************************************************************
00119  ********************************************************************/
00120 
00121 static BOOL elog_validate_logname( const char *name )
00122 {
00123         int i;
00124         const char **elogs = lp_eventlog_list();
00125         
00126         if (!elogs) {
00127                 return False;
00128         }
00129 
00130         for ( i=0; elogs[i]; i++ ) {
00131                 if ( strequal( name, elogs[i] ) )
00132                         return True;
00133         }
00134         
00135         return False;
00136 }
00137 
00138 /********************************************************************
00139 ********************************************************************/
00140 
00141 static BOOL get_num_records_hook( EVENTLOG_INFO * info )
00142 {
00143         int next_record;
00144         int oldest_record;
00145 
00146         if ( !info->etdb ) {
00147                 DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
00148                 return False;
00149         }
00150 
00151         /* lock the tdb since we have to get 2 records */
00152 
00153         tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
00154         next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
00155         oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
00156         tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
00157 
00158         DEBUG( 8,
00159                ( "Oldest Record %d; Next Record %d\n", oldest_record,
00160                  next_record ) );
00161 
00162         info->num_records = ( next_record - oldest_record );
00163         info->oldest_entry = oldest_record;
00164 
00165         return True;
00166 }
00167 
00168 /********************************************************************
00169  ********************************************************************/
00170 
00171 static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info )
00172 {
00173         /* it's the same thing */
00174         return get_num_records_hook( info );
00175 }
00176 
00177 /********************************************************************
00178  ********************************************************************/
00179 
00180 static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd )
00181 {
00182         EVENTLOG_INFO *elog;
00183         
00184         /* first thing is to validate the eventlog name */
00185         
00186         if ( !elog_validate_logname( logname ) )
00187                 return NT_STATUS_OBJECT_PATH_INVALID;
00188         
00189         if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) )
00190                 return NT_STATUS_NO_MEMORY;
00191                 
00192         elog->logname = talloc_strdup( elog, logname );
00193         
00194         /* Open the tdb first (so that we can create any new tdbs if necessary).
00195            We have to do this as root and then use an internal access check 
00196            on the file permissions since you can only have a tdb open once
00197            in a single process */
00198 
00199         become_root();
00200         elog->etdb = elog_open_tdb( elog->logname, False );
00201         unbecome_root();
00202 
00203         if ( !elog->etdb ) {
00204                 /* according to MSDN, if the logfile cannot be found, we should
00205                   default to the "Application" log */
00206         
00207                 if ( !strequal( logname, ELOG_APPL ) ) {
00208                 
00209                         TALLOC_FREE( elog->logname );
00210                         
00211                         elog->logname = talloc_strdup( elog, ELOG_APPL );                       
00212 
00213                         /* do the access check */
00214                         if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
00215                                 TALLOC_FREE( elog );
00216                                 return NT_STATUS_ACCESS_DENIED;
00217                         }
00218         
00219                         become_root();
00220                         elog->etdb = elog_open_tdb( elog->logname, False );
00221                         unbecome_root();
00222                 }       
00223                 
00224                 if ( !elog->etdb ) {
00225                         TALLOC_FREE( elog );
00226                         return NT_STATUS_ACCESS_DENIED; /* ??? */               
00227                 }
00228         }
00229         
00230         /* now do the access check.  Close the tdb if we fail here */
00231 
00232         if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
00233                 elog_close_tdb( elog->etdb, False );
00234                 TALLOC_FREE( elog );
00235                 return NT_STATUS_ACCESS_DENIED;
00236         }
00237         
00238         /* create the policy handle */
00239         
00240         if ( !create_policy_hnd
00241              ( p, hnd, free_eventlog_info, ( void * ) elog ) ) {
00242                 free_eventlog_info( elog );
00243                 return NT_STATUS_NO_MEMORY;
00244         }
00245 
00246         /* set the initial current_record pointer */
00247 
00248         if ( !get_oldest_entry_hook( elog ) ) {
00249                 DEBUG(3,("elog_open: Successfully opened eventlog but can't "
00250                         "get any information on internal records!\n"));
00251         }       
00252 
00253         elog->current_record = elog->oldest_entry;
00254 
00255         return NT_STATUS_OK;
00256 }
00257 
00258 /********************************************************************
00259  ********************************************************************/
00260 
00261 static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
00262 {
00263         if ( !( close_policy_hnd( p, hnd ) ) ) {
00264                 return NT_STATUS_INVALID_HANDLE;
00265         }
00266 
00267         return NT_STATUS_OK;
00268 }
00269 
00270 /*******************************************************************
00271  *******************************************************************/
00272 
00273 static int elog_size( EVENTLOG_INFO *info )
00274 {
00275         if ( !info || !info->etdb ) {
00276                 DEBUG(0,("elog_size: Invalid info* structure!\n"));
00277                 return 0;
00278         }
00279 
00280         return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
00281 }
00282 
00283 /********************************************************************
00284   For the given tdb, get the next eventlog record into the passed 
00285   Eventlog_entry.  returns NULL if it can't get the record for some reason.
00286  ********************************************************************/
00287 
00288 static Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
00289                                      int recno, Eventlog_entry * ee )
00290 {
00291         TDB_DATA ret, key;
00292 
00293         int srecno;
00294         int reclen;
00295         int len;
00296 
00297         pstring *wpsource, *wpcomputer, *wpsid, *wpstrs, *puserdata;
00298 
00299         key.dsize = sizeof( int32 );
00300 
00301         srecno = recno;
00302         key.dptr = ( char * ) &srecno;
00303 
00304         ret = tdb_fetch( tdb, key );
00305 
00306         if ( ret.dsize == 0 ) {
00307                 DEBUG( 8,
00308                        ( "Can't find a record for the key, record %d\n",
00309                          recno ) );
00310                 return NULL;
00311         }
00312 
00313         len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen );
00314 
00315         DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) );
00316 
00317         if ( !len )
00318                 return NULL;
00319 
00320         /* ee = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); */
00321 
00322         if ( !ee )
00323                 return NULL;
00324 
00325         len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd",
00326                           &ee->record.length, &ee->record.reserved1,
00327                           &ee->record.record_number,
00328                           &ee->record.time_generated,
00329                           &ee->record.time_written, &ee->record.event_id,
00330                           &ee->record.event_type, &ee->record.num_strings,
00331                           &ee->record.event_category, &ee->record.reserved2,
00332                           &ee->record.closing_record_number,
00333                           &ee->record.string_offset,
00334                           &ee->record.user_sid_length,
00335                           &ee->record.user_sid_offset,
00336                           &ee->record.data_length, &ee->record.data_offset,
00337                           &ee->data_record.source_name_len, &wpsource,
00338                           &ee->data_record.computer_name_len, &wpcomputer,
00339                           &ee->data_record.sid_padding,
00340                           &ee->record.user_sid_length, &wpsid,
00341                           &ee->data_record.strings_len, &wpstrs,
00342                           &ee->data_record.user_data_len, &puserdata,
00343                           &ee->data_record.data_padding );
00344         DEBUG( 10,
00345                ( "Read record %d, len in tdb was %d\n",
00346                  ee->record.record_number, len ) );
00347 
00348         /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff
00349            into it's 2nd argment for 'B' */
00350 
00351         if ( wpcomputer )
00352                 memcpy( ee->data_record.computer_name, wpcomputer,
00353                         ee->data_record.computer_name_len );
00354         if ( wpsource )
00355                 memcpy( ee->data_record.source_name, wpsource,
00356                         ee->data_record.source_name_len );
00357 
00358         if ( wpsid )
00359                 memcpy( ee->data_record.sid, wpsid,
00360                         ee->record.user_sid_length );
00361         if ( wpstrs )
00362                 memcpy( ee->data_record.strings, wpstrs,
00363                         ee->data_record.strings_len );
00364 
00365         /* note that userdata is a pstring */
00366         if ( puserdata )
00367                 memcpy( ee->data_record.user_data, puserdata,
00368                         ee->data_record.user_data_len );
00369 
00370         SAFE_FREE( wpcomputer );
00371         SAFE_FREE( wpsource );
00372         SAFE_FREE( wpsid );
00373         SAFE_FREE( wpstrs );
00374         SAFE_FREE( puserdata );
00375 
00376         DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) );
00377         DEBUG( 10,
00378                ( "get_eventlog_record: computer_name %d is ",
00379                  ee->data_record.computer_name_len ) );
00380         SAFE_FREE( ret.dptr );
00381         return ee;
00382 }
00383 
00384 /********************************************************************
00385  note that this can only be called AFTER the table is constructed, 
00386  since it uses the table to find the tdb handle
00387  ********************************************************************/
00388 
00389 static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
00390 {
00391         pstring path;
00392         uint32 uiMaxSize;
00393         uint32 uiRetention;
00394         REGISTRY_KEY *keyinfo;
00395         REGISTRY_VALUE *val;
00396         REGVAL_CTR *values;
00397         WERROR wresult;
00398         char *elogname = info->logname;
00399 
00400         DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
00401 
00402         if ( !info->etdb ) {
00403                 DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
00404                 return False;
00405         }
00406         /* set resonable defaults.  512Kb on size and 1 week on time */
00407 
00408         uiMaxSize = 0x80000;
00409         uiRetention = 604800;
00410 
00411         /* the general idea is to internally open the registry 
00412            key and retreive the values.  That way we can continue 
00413            to use the same fetch/store api that we use in 
00414            srv_reg_nt.c */
00415 
00416         pstr_sprintf( path, "%s/%s", KEY_EVENTLOG, elogname );
00417 
00418         wresult =
00419                 regkey_open_internal( &keyinfo, path, get_root_nt_token(  ),
00420                                       REG_KEY_READ );
00421 
00422         if ( !W_ERROR_IS_OK( wresult ) ) {
00423                 DEBUG( 4,
00424                        ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
00425                          path, dos_errstr( wresult ) ) );
00426                 return False;
00427         }
00428 
00429         if ( !( values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR ) ) ) {
00430                 TALLOC_FREE( keyinfo );
00431                 DEBUG( 0, ( "control_eventlog_hook: talloc() failed!\n" ) );
00432 
00433                 return False;
00434         }
00435         fetch_reg_values( keyinfo, values );
00436 
00437         if ( ( val = regval_ctr_getvalue( values, "Retention" ) ) != NULL )
00438                 uiRetention = IVAL( regval_data_p( val ), 0 );
00439 
00440         if ( ( val = regval_ctr_getvalue( values, "MaxSize" ) ) != NULL )
00441                 uiMaxSize = IVAL( regval_data_p( val ), 0 );
00442 
00443         regkey_close_internal( keyinfo );
00444 
00445         tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
00446         tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
00447 
00448         return True;
00449 }
00450 
00451 /********************************************************************
00452  ********************************************************************/
00453 
00454 static Eventlog_entry *read_package_entry( prs_struct * ps,
00455                                            EVENTLOG_Q_READ_EVENTLOG * q_u,
00456                                            EVENTLOG_R_READ_EVENTLOG * r_u,
00457                                            Eventlog_entry * entry )
00458 {
00459         uint8 *offset;
00460         Eventlog_entry *ee_new = NULL;
00461 
00462         ee_new = PRS_ALLOC_MEM( ps, Eventlog_entry, 1 );
00463         if ( ee_new == NULL ) {
00464                 return NULL;
00465         }
00466 
00467         entry->data_record.sid_padding =
00468                 ( ( 4 -
00469                     ( ( entry->data_record.source_name_len +
00470                         entry->data_record.computer_name_len ) % 4 ) ) % 4 );
00471         entry->data_record.data_padding =
00472                 ( 4 -
00473                   ( ( entry->data_record.strings_len +
00474                       entry->data_record.user_data_len ) % 4 ) ) % 4;
00475         entry->record.length = sizeof( Eventlog_record );
00476         entry->record.length += entry->data_record.source_name_len;
00477         entry->record.length += entry->data_record.computer_name_len;
00478         if ( entry->record.user_sid_length == 0 ) {
00479                 /* Should not pad to a DWORD boundary for writing out the sid if there is
00480                    no SID, so just propagate the padding to pad the data */
00481                 entry->data_record.data_padding +=
00482                         entry->data_record.sid_padding;
00483                 entry->data_record.sid_padding = 0;
00484         }
00485         DEBUG( 10,
00486                ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) );
00487         DEBUG( 10,
00488                ( "data_padding is [%d].\n",
00489                  entry->data_record.data_padding ) );
00490 
00491         entry->record.length += entry->data_record.sid_padding;
00492         entry->record.length += entry->record.user_sid_length;
00493         entry->record.length += entry->data_record.strings_len;
00494         entry->record.length += entry->data_record.user_data_len;
00495         entry->record.length += entry->data_record.data_padding;
00496         /* need another copy of length at the end of the data */
00497         entry->record.length += sizeof( entry->record.length );
00498         DEBUG( 10,
00499                ( "entry->record.length is [%d].\n", entry->record.length ) );
00500         entry->data =
00501                 PRS_ALLOC_MEM( ps, uint8,
00502                                entry->record.length -
00503                                sizeof( Eventlog_record ) -
00504                                sizeof( entry->record.length ) );
00505         if ( entry->data == NULL ) {
00506                 return NULL;
00507         }
00508         offset = entry->data;
00509         memcpy( offset, &( entry->data_record.source_name ),
00510                 entry->data_record.source_name_len );
00511         offset += entry->data_record.source_name_len;
00512         memcpy( offset, &( entry->data_record.computer_name ),
00513                 entry->data_record.computer_name_len );
00514         offset += entry->data_record.computer_name_len;
00515         /* SID needs to be DWORD-aligned */
00516         offset += entry->data_record.sid_padding;
00517         entry->record.user_sid_offset =
00518                 sizeof( Eventlog_record ) + ( offset - entry->data );
00519         memcpy( offset, &( entry->data_record.sid ),
00520                 entry->record.user_sid_length );
00521         offset += entry->record.user_sid_length;
00522         /* Now do the strings */
00523         entry->record.string_offset =
00524                 sizeof( Eventlog_record ) + ( offset - entry->data );
00525         memcpy( offset, &( entry->data_record.strings ),
00526                 entry->data_record.strings_len );
00527         offset += entry->data_record.strings_len;
00528         /* Now do the data */
00529         entry->record.data_length = entry->data_record.user_data_len;
00530         entry->record.data_offset =
00531                 sizeof( Eventlog_record ) + ( offset - entry->data );
00532         memcpy( offset, &( entry->data_record.user_data ),
00533                 entry->data_record.user_data_len );
00534         offset += entry->data_record.user_data_len;
00535 
00536         memcpy( &( ee_new->record ), &entry->record,
00537                 sizeof( Eventlog_record ) );
00538         memcpy( &( ee_new->data_record ), &entry->data_record,
00539                 sizeof( Eventlog_data_record ) );
00540         ee_new->data = entry->data;
00541 
00542         return ee_new;
00543 }
00544 
00545 /********************************************************************
00546  ********************************************************************/
00547 
00548 static BOOL add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
00549                                 Eventlog_entry * ee_new )
00550 {
00551         Eventlog_entry *insert_point;
00552 
00553         insert_point = r_u->entry;
00554 
00555         if ( NULL == insert_point ) {
00556                 r_u->entry = ee_new;
00557                 ee_new->next = NULL;
00558         } else {
00559                 while ( ( NULL != insert_point->next ) ) {
00560                         insert_point = insert_point->next;
00561                 }
00562                 ee_new->next = NULL;
00563                 insert_point->next = ee_new;
00564         }
00565         r_u->num_records++;
00566         r_u->num_bytes_in_resp += ee_new->record.length;
00567 
00568         return True;
00569 }
00570 
00571 /********************************************************************
00572  ********************************************************************/
00573 
00574 NTSTATUS _eventlog_open_eventlog( pipes_struct * p,
00575                                 EVENTLOG_Q_OPEN_EVENTLOG * q_u,
00576                                 EVENTLOG_R_OPEN_EVENTLOG * r_u )
00577 {
00578         fstring servername, logname;
00579         EVENTLOG_INFO *info;
00580         NTSTATUS result;
00581 
00582         fstrcpy( servername, "" );
00583         if ( q_u->servername.string ) {
00584                 rpcstr_pull( servername, q_u->servername.string->buffer,
00585                              sizeof( servername ),
00586                              q_u->servername.string->uni_str_len * 2, 0 );
00587         }
00588 
00589         fstrcpy( logname, "" );
00590         if ( q_u->logname.string ) {
00591                 rpcstr_pull( logname, q_u->logname.string->buffer,
00592                              sizeof( logname ),
00593                              q_u->logname.string->uni_str_len * 2, 0 );
00594         }
00595         
00596         DEBUG( 10,("_eventlog_open_eventlog: Server [%s], Log [%s]\n",
00597                 servername, logname ));
00598                 
00599         /* according to MSDN, if the logfile cannot be found, we should
00600           default to the "Application" log */
00601           
00602         if ( !NT_STATUS_IS_OK( result = elog_open( p, logname, &r_u->handle )) )
00603                 return result;
00604 
00605         if ( !(info = find_eventlog_info_by_hnd( p, &r_u->handle )) ) {
00606                 DEBUG(0,("_eventlog_open_eventlog: eventlog (%s) opened but unable to find handle!\n",
00607                         logname ));
00608                 elog_close( p, &r_u->handle );
00609                 return NT_STATUS_INVALID_HANDLE;
00610         }
00611 
00612         DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info )));
00613 
00614         sync_eventlog_params( info );
00615         prune_eventlog( ELOG_TDB_CTX(info->etdb) );
00616 
00617         return NT_STATUS_OK;
00618 }
00619 
00620 /********************************************************************
00621  This call still needs some work
00622  ********************************************************************/
00623 
00624 NTSTATUS _eventlog_clear_eventlog( pipes_struct * p,
00625                                  EVENTLOG_Q_CLEAR_EVENTLOG * q_u,
00626                                  EVENTLOG_R_CLEAR_EVENTLOG * r_u )
00627 {
00628         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
00629         pstring backup_file_name;
00630 
00631         if ( !info )
00632                 return NT_STATUS_INVALID_HANDLE;
00633 
00634         pstrcpy( backup_file_name, "" );
00635         if ( q_u->backupfile.string ) {
00636                 rpcstr_pull( backup_file_name, q_u->backupfile.string->buffer,
00637                              sizeof( backup_file_name ),
00638                              q_u->backupfile.string->uni_str_len * 2, 0 );
00639 
00640                 DEBUG(8,( "_eventlog_clear_eventlog: Using [%s] as the backup "
00641                         "file name for log [%s].",
00642                          backup_file_name, info->logname ) );
00643         }
00644 
00645         /* check for WRITE access to the file */
00646 
00647         if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
00648                 return NT_STATUS_ACCESS_DENIED;
00649 
00650         /* Force a close and reopen */
00651 
00652         elog_close_tdb( info->etdb, True ); 
00653         become_root();
00654         info->etdb = elog_open_tdb( info->logname, True );
00655         unbecome_root();
00656 
00657         if ( !info->etdb )
00658                 return NT_STATUS_ACCESS_DENIED;
00659 
00660         return NT_STATUS_OK;
00661 }
00662 
00663 /********************************************************************
00664  ********************************************************************/
00665 
00666 NTSTATUS _eventlog_close_eventlog( pipes_struct * p,
00667                                  EVENTLOG_Q_CLOSE_EVENTLOG * q_u,
00668                                  EVENTLOG_R_CLOSE_EVENTLOG * r_u )
00669 {
00670         return elog_close( p, &q_u->handle );
00671 }
00672 
00673 /********************************************************************
00674  ********************************************************************/
00675 
00676 NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
00677                                 EVENTLOG_Q_READ_EVENTLOG * q_u,
00678                                 EVENTLOG_R_READ_EVENTLOG * r_u )
00679 {
00680         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
00681         Eventlog_entry entry, *ee_new;
00682         uint32 num_records_read = 0;
00683         prs_struct *ps;
00684         int bytes_left, record_number;
00685         uint32 elog_read_type, elog_read_dir;
00686 
00687         if (info == NULL) {
00688                 return NT_STATUS_INVALID_HANDLE;
00689         }
00690 
00691         info->flags = q_u->flags;
00692         ps = &p->out_data.rdata;
00693 
00694         bytes_left = q_u->max_read_size;
00695 
00696         if ( !info->etdb ) 
00697                 return NT_STATUS_ACCESS_DENIED;
00698                 
00699         /* check for valid flags.  Can't use the sequential and seek flags together */
00700 
00701         elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
00702         elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
00703 
00704         if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) 
00705                 ||  elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) )
00706         {
00707                 DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags));
00708                 return NT_STATUS_INVALID_PARAMETER;
00709         }
00710 
00711         /* a sequential read should ignore the offset */
00712 
00713         if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ )
00714                 record_number = info->current_record;
00715         else 
00716                 record_number = q_u->offset;
00717 
00718         while ( bytes_left > 0 ) {
00719 
00720                 /* assume that when the record fetch fails, that we are done */
00721 
00722                 if ( !get_eventlog_record ( ps, ELOG_TDB_CTX(info->etdb), record_number, &entry ) ) 
00723                         break;
00724 
00725                 DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
00726                                
00727                 /* Now see if there is enough room to add */
00728 
00729                 if ( !(ee_new = read_package_entry( ps, q_u, r_u,&entry )) )
00730                         return NT_STATUS_NO_MEMORY;
00731 
00732                 if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) {
00733                         r_u->bytes_in_next_record = ee_new->record.length;
00734 
00735                         /* response would be too big to fit in client-size buffer */
00736                                 
00737                         bytes_left = 0;
00738                         break;
00739                 }
00740                         
00741                 add_record_to_resp( r_u, ee_new );
00742                 bytes_left -= ee_new->record.length;
00743                 ZERO_STRUCT( entry );
00744                 num_records_read = r_u->num_records - num_records_read;
00745                                 
00746                 DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total "
00747                         "of [%d] records using [%d] bytes out of a max of [%d].\n",
00748                          num_records_read, r_u->num_records,
00749                          r_u->num_bytes_in_resp,
00750                          q_u->max_read_size ) );
00751 
00752                 if ( info->flags & EVENTLOG_FORWARDS_READ )
00753                         record_number++;
00754                 else
00755                         record_number--;
00756                 
00757                 /* update the eventlog record pointer */
00758                 
00759                 info->current_record = record_number;
00760         }
00761 
00762         /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to 
00763            say when there are no more records */
00764 
00765         return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL);
00766 }
00767 
00768 /********************************************************************
00769  ********************************************************************/
00770 
00771 NTSTATUS _eventlog_get_oldest_entry( pipes_struct * p,
00772                                    EVENTLOG_Q_GET_OLDEST_ENTRY * q_u,
00773                                    EVENTLOG_R_GET_OLDEST_ENTRY * r_u )
00774 {
00775         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
00776 
00777         if (info == NULL) {
00778                 return NT_STATUS_INVALID_HANDLE;
00779         }
00780 
00781         if ( !( get_oldest_entry_hook( info ) ) )
00782                 return NT_STATUS_ACCESS_DENIED;
00783 
00784         r_u->oldest_entry = info->oldest_entry;
00785 
00786         return NT_STATUS_OK;
00787 }
00788 
00789 /********************************************************************
00790  ********************************************************************/
00791 
00792 NTSTATUS _eventlog_get_num_records( pipes_struct * p,
00793                                   EVENTLOG_Q_GET_NUM_RECORDS * q_u,
00794                                   EVENTLOG_R_GET_NUM_RECORDS * r_u )
00795 {
00796         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
00797 
00798         if (info == NULL) {
00799                 return NT_STATUS_INVALID_HANDLE;
00800         }
00801 
00802         if ( !( get_num_records_hook( info ) ) )
00803                 return NT_STATUS_ACCESS_DENIED;
00804 
00805         r_u->num_records = info->num_records;
00806 
00807         return NT_STATUS_OK;
00808 }

Sambaに対してSat Aug 29 21:23:19 2009に生成されました。  doxygen 1.4.7