00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 struct rcinit_file_information {
00027 char *description;
00028 };
00029
00030 struct service_display_info {
00031 const char *servicename;
00032 const char *daemon;
00033 const char *dispname;
00034 const char *description;
00035 };
00036
00037 struct service_display_info builtin_svcs[] = {
00038 { "Spooler", "smbd", "Print Spooler", "Internal service for spooling files to print devices" },
00039 { "NETLOGON", "smbd", "Net Logon", "File service providing access to policy and profile data (not remotely manageable)" },
00040 { "RemoteRegistry", "smbd", "Remote Registry Service", "Internal service providing remote access to "
00041 "the Samba registry" },
00042 { "WINS", "nmbd", "Windows Internet Name Service (WINS)", "Internal service providing a "
00043 "NetBIOS point-to-point name server (not remotely manageable)" },
00044 { NULL, NULL, NULL, NULL }
00045 };
00046
00047 struct service_display_info common_unix_svcs[] = {
00048 { "cups", NULL, "Common Unix Printing System","Provides unified printing support for all operating systems" },
00049 { "postfix", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
00050 { "sendmail", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
00051 { "portmap", NULL, "TCP Port to RPC PortMapper",NULL },
00052 { "xinetd", NULL, "Internet Meta-Daemon", NULL },
00053 { "inet", NULL, "Internet Meta-Daemon", NULL },
00054 { "xntpd", NULL, "Network Time Service", NULL },
00055 { "ntpd", NULL, "Network Time Service", NULL },
00056 { "lpd", NULL, "BSD Print Spooler", NULL },
00057 { "nfsserver", NULL, "Network File Service", NULL },
00058 { "cron", NULL, "Scheduling Service", NULL },
00059 { "at", NULL, "Scheduling Service", NULL },
00060 { "nscd", NULL, "Name Service Cache Daemon", NULL },
00061 { "slapd", NULL, "LDAP Directory Service", NULL },
00062 { "ldap", NULL, "LDAP DIrectory Service", NULL },
00063 { "ypbind", NULL, "NIS Directory Service", NULL },
00064 { "courier-imap", NULL, "IMAP4 Mail Service", NULL },
00065 { "courier-pop3", NULL, "POP3 Mail Service", NULL },
00066 { "named", NULL, "Domain Name Service", NULL },
00067 { "bind", NULL, "Domain Name Service", NULL },
00068 { "httpd", NULL, "HTTP Server", NULL },
00069 { "apache", NULL, "HTTP Server", "Provides s highly scalable and flexible web server "
00070 "capable of implementing various protocols incluing "
00071 "but not limited to HTTP" },
00072 { "autofs", NULL, "Automounter", NULL },
00073 { "squid", NULL, "Web Cache Proxy ", NULL },
00074 { "perfcountd", NULL, "Performance Monitoring Daemon", NULL },
00075 { "pgsql", NULL, "PgSQL Database Server", "Provides service for SQL database from Postgresql.org" },
00076 { "arpwatch", NULL, "ARP Tables watcher", "Provides service for monitoring ARP tables for changes" },
00077 { "dhcpd", NULL, "DHCP Server", "Provides service for dynamic host configuration and IP assignment" },
00078 { "nwserv", NULL, "NetWare Server Emulator", "Provides service for emulating Novell NetWare 3.12 server" },
00079 { "proftpd", NULL, "Professional FTP Server", "Provides high configurable service for FTP connection and "
00080 "file transferring" },
00081 { "ssh2", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
00082 { "sshd", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
00083 { NULL, NULL, NULL, NULL }
00084 };
00085
00086
00087
00088
00089
00090 static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
00091 {
00092 SEC_ACE ace[4];
00093 SEC_ACCESS mask;
00094 size_t i = 0;
00095 SEC_DESC *sd;
00096 SEC_ACL *acl;
00097 size_t sd_size;
00098
00099
00100
00101 init_sec_access(&mask, SERVICE_READ_ACCESS );
00102 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00103
00104 init_sec_access(&mask,SERVICE_EXECUTE_ACCESS );
00105 init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00106
00107 init_sec_access(&mask,SERVICE_ALL_ACCESS );
00108 init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00109 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00110
00111
00112
00113 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
00114 return NULL;
00115
00116 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
00117 return NULL;
00118
00119 return sd;
00120 }
00121
00122
00123
00124
00125
00126
00127 static char *get_common_service_dispname( const char *servicename )
00128 {
00129 static fstring dispname;
00130 int i;
00131
00132 for ( i=0; common_unix_svcs[i].servicename; i++ ) {
00133 if ( strequal( servicename, common_unix_svcs[i].servicename ) ) {
00134 fstr_sprintf( dispname, "%s (%s)",
00135 common_unix_svcs[i].dispname,
00136 common_unix_svcs[i].servicename );
00137
00138 return dispname;
00139 }
00140 }
00141
00142 fstrcpy( dispname, servicename );
00143
00144 return dispname;
00145 }
00146
00147
00148
00149
00150 static char* cleanup_string( const char *string )
00151 {
00152 static pstring clean;
00153 char *begin, *end;
00154
00155 pstrcpy( clean, string );
00156 begin = clean;
00157
00158
00159
00160 while ( isspace(*begin) )
00161 begin++;
00162
00163 if ( *begin == '\0' )
00164 return NULL;
00165
00166
00167
00168
00169 end = begin + strlen(begin) - 1;
00170
00171 while ( isspace(*end) || *end=='\n' || *end=='\r' ) {
00172 *end = '\0';
00173 end--;
00174 }
00175
00176 return begin;
00177 }
00178
00179
00180
00181
00182 static BOOL read_init_file( const char *servicename, struct rcinit_file_information **service_info )
00183 {
00184 struct rcinit_file_information *info;
00185 pstring filepath, str;
00186 XFILE *f;
00187 char *p;
00188
00189 if ( !(info = TALLOC_ZERO_P( NULL, struct rcinit_file_information ) ) )
00190 return False;
00191
00192
00193
00194 pstr_sprintf( filepath, "%s/%s/%s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, servicename );
00195 if ( !(f = x_fopen( filepath, O_RDONLY, 0 )) ) {
00196 DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
00197 TALLOC_FREE(info);
00198 return False;
00199 }
00200
00201 while ( (x_fgets( str, sizeof(str)-1, f )) != NULL ) {
00202
00203
00204
00205 if ( str[0] != '#' )
00206 continue;
00207
00208
00209
00210 if ( (p = strstr( str, "Description:" )) != NULL ) {
00211 char *desc;
00212
00213 p += strlen( "Description:" ) + 1;
00214 if ( !p )
00215 break;
00216
00217 if ( (desc = cleanup_string(p)) != NULL )
00218 info->description = talloc_strdup( info, desc );
00219 }
00220 }
00221
00222 x_fclose( f );
00223
00224 if ( !info->description )
00225 info->description = talloc_strdup( info, "External Unix Service" );
00226
00227 *service_info = info;
00228
00229 return True;
00230 }
00231
00232
00233
00234
00235
00236
00237 static void fill_service_values( const char *name, REGVAL_CTR *values )
00238 {
00239 UNISTR2 data, dname, ipath, description;
00240 uint32 dword;
00241 pstring pstr;
00242 int i;
00243
00244
00245
00246
00247 dword = SVCCTL_AUTO_START;
00248 regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32));
00249
00250 dword = SVCCTL_WIN32_OWN_PROC;
00251 regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32));
00252
00253 dword = SVCCTL_SVC_ERROR_NORMAL;
00254 regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32));
00255
00256
00257
00258 init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE );
00259 regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2);
00260
00261
00262
00263 for ( i=0; builtin_svcs[i].servicename; i++ ) {
00264 if ( strequal( name, builtin_svcs[i].servicename ) ) {
00265 pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, builtin_svcs[i].daemon );
00266 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
00267 init_unistr2( &description, builtin_svcs[i].description, UNI_STR_TERMINATE );
00268 init_unistr2( &dname, builtin_svcs[i].dispname, UNI_STR_TERMINATE );
00269 break;
00270 }
00271 }
00272
00273
00274
00275 if ( builtin_svcs[i].servicename == NULL ) {
00276 struct rcinit_file_information *init_info = NULL;
00277
00278 pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name );
00279 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
00280
00281
00282 init_unistr2( &dname, get_common_service_dispname( name ), UNI_STR_TERMINATE );
00283
00284
00285 if ( read_init_file( name, &init_info ) ) {
00286 init_unistr2( &description, init_info->description, UNI_STR_TERMINATE );
00287 TALLOC_FREE( init_info );
00288 }
00289 else {
00290 init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
00291 }
00292 }
00293
00294
00295
00296 regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2);
00297 regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2);
00298 regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2);
00299
00300 return;
00301 }
00302
00303
00304
00305
00306 static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys,
00307 const char *name )
00308 {
00309 REGISTRY_KEY *key_service, *key_secdesc;
00310 WERROR wresult;
00311 pstring path;
00312 REGVAL_CTR *values;
00313 REGSUBKEY_CTR *svc_subkeys;
00314 SEC_DESC *sd;
00315 prs_struct ps;
00316
00317
00318
00319 regsubkey_ctr_addkey( subkeys, name );
00320 store_reg_keys( key_parent, subkeys );
00321
00322
00323
00324 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
00325 wresult = regkey_open_internal( &key_service, path, get_root_nt_token(),
00326 REG_KEY_ALL );
00327 if ( !W_ERROR_IS_OK(wresult) ) {
00328 DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
00329 path, dos_errstr(wresult)));
00330 return;
00331 }
00332
00333
00334
00335 if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) {
00336 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
00337 regkey_close_internal( key_service );
00338 return;
00339 }
00340
00341 fetch_reg_keys( key_service, svc_subkeys );
00342 regsubkey_ctr_addkey( svc_subkeys, "Security" );
00343 store_reg_keys( key_service, svc_subkeys );
00344
00345
00346
00347 if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) {
00348 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
00349 regkey_close_internal( key_service );
00350 return;
00351 }
00352
00353 fill_service_values( name, values );
00354 store_reg_values( key_service, values );
00355
00356
00357
00358 regkey_close_internal( key_service );
00359
00360
00361
00362 pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
00363 wresult = regkey_open_internal( &key_secdesc, path, get_root_nt_token(),
00364 REG_KEY_ALL );
00365 if ( !W_ERROR_IS_OK(wresult) ) {
00366 DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
00367 path, dos_errstr(wresult)));
00368 regkey_close_internal( key_secdesc );
00369 return;
00370 }
00371
00372 if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) {
00373 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
00374 regkey_close_internal( key_secdesc );
00375 return;
00376 }
00377
00378 if ( !(sd = construct_service_sd(key_secdesc)) ) {
00379 DEBUG(0,("add_new_svc_name: Failed to create default sec_desc!\n"));
00380 regkey_close_internal( key_secdesc );
00381 return;
00382 }
00383
00384
00385
00386 prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key_secdesc, MARSHALL);
00387
00388 if ( sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
00389 uint32 offset = prs_offset( &ps );
00390 regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset );
00391 store_reg_values( key_secdesc, values );
00392 }
00393
00394
00395
00396 prs_mem_free( &ps );
00397 regkey_close_internal( key_secdesc );
00398
00399 return;
00400 }
00401
00402
00403
00404
00405 void svcctl_init_keys( void )
00406 {
00407 const char **service_list = lp_svcctl_list();
00408 int i;
00409 REGSUBKEY_CTR *subkeys;
00410 REGISTRY_KEY *key = NULL;
00411 WERROR wresult;
00412
00413
00414
00415 wresult = regkey_open_internal( &key, KEY_SERVICES, get_root_nt_token(),
00416 REG_KEY_ALL );
00417
00418 if ( !W_ERROR_IS_OK(wresult) ) {
00419 DEBUG(0,("svcctl_init_keys: key lookup failed! (%s)\n",
00420 dos_errstr(wresult)));
00421 return;
00422 }
00423
00424
00425
00426 if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
00427 DEBUG(0,("svcctl_init_keys: talloc() failed!\n"));
00428 regkey_close_internal( key );
00429 return;
00430 }
00431
00432 fetch_reg_keys( key, subkeys );
00433
00434
00435
00436 for ( i=0; builtin_svcs[i].servicename; i++ )
00437 add_new_svc_name( key, subkeys, builtin_svcs[i].servicename );
00438
00439 for ( i=0; service_list && service_list[i]; i++ ) {
00440
00441
00442 if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) )
00443 continue;
00444
00445
00446
00447 add_new_svc_name( key, subkeys, service_list[i] );
00448 }
00449
00450 regkey_close_internal( key );
00451
00452
00453
00454 init_service_op_table();
00455
00456 return;
00457 }
00458
00459
00460
00461
00462
00463
00464
00465 SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
00466 {
00467 REGISTRY_KEY *key;
00468 prs_struct ps;
00469 REGVAL_CTR *values;
00470 REGISTRY_VALUE *val;
00471 SEC_DESC *sd = NULL;
00472 SEC_DESC *ret_sd = NULL;
00473 pstring path;
00474 WERROR wresult;
00475
00476
00477
00478 pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
00479 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
00480 if ( !W_ERROR_IS_OK(wresult) ) {
00481 DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n",
00482 path, dos_errstr(wresult)));
00483 return NULL;
00484 }
00485
00486 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
00487 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
00488 regkey_close_internal( key );
00489 return NULL;
00490 }
00491
00492 fetch_reg_values( key, values );
00493
00494 if ( !(val = regval_ctr_getvalue( values, "Security" )) ) {
00495 DEBUG(6,("svcctl_get_secdesc: constructing default secdesc for service [%s]\n",
00496 name));
00497 regkey_close_internal( key );
00498 return construct_service_sd( ctx );
00499 }
00500
00501
00502
00503
00504 prs_init( &ps, 0, key, UNMARSHALL);
00505 prs_give_memory( &ps, (char *)regval_data_p(val), regval_size(val), False );
00506
00507 if ( !sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
00508 regkey_close_internal( key );
00509 return construct_service_sd( ctx );
00510 }
00511
00512 ret_sd = dup_sec_desc( ctx, sd );
00513
00514
00515
00516 prs_mem_free( &ps );
00517 regkey_close_internal( key );
00518
00519 return ret_sd;
00520 }
00521
00522
00523
00524
00525
00526 BOOL svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, NT_USER_TOKEN *token )
00527 {
00528 REGISTRY_KEY *key;
00529 WERROR wresult;
00530 pstring path;
00531 REGVAL_CTR *values;
00532 prs_struct ps;
00533 BOOL ret = False;
00534
00535
00536
00537 pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
00538 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
00539 if ( !W_ERROR_IS_OK(wresult) ) {
00540 DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n",
00541 path, dos_errstr(wresult)));
00542 return False;
00543 }
00544
00545 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
00546 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
00547 regkey_close_internal( key );
00548 return False;
00549 }
00550
00551
00552
00553 prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key, MARSHALL);
00554
00555 if ( sec_io_desc("sec_desc", &sec_desc, &ps, 0 ) ) {
00556 uint32 offset = prs_offset( &ps );
00557 regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset );
00558 ret = store_reg_values( key, values );
00559 }
00560
00561
00562
00563 prs_mem_free( &ps );
00564 regkey_close_internal( key);
00565
00566 return ret;
00567 }
00568
00569
00570
00571
00572 char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token )
00573 {
00574 static fstring display_name;
00575 REGISTRY_KEY *key;
00576 REGVAL_CTR *values;
00577 REGISTRY_VALUE *val;
00578 pstring path;
00579 WERROR wresult;
00580
00581
00582
00583 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
00584 wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
00585 if ( !W_ERROR_IS_OK(wresult) ) {
00586 DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
00587 path, dos_errstr(wresult)));
00588 goto fail;
00589 }
00590
00591 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
00592 DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
00593 regkey_close_internal( key );
00594 goto fail;
00595 }
00596
00597 fetch_reg_values( key, values );
00598
00599 if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) )
00600 goto fail;
00601
00602 rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 );
00603
00604 regkey_close_internal( key );
00605
00606 return display_name;
00607
00608 fail:
00609
00610 regkey_close_internal( key );
00611 fstrcpy( display_name, name );
00612 return display_name;
00613 }
00614
00615
00616
00617
00618 char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token )
00619 {
00620 static fstring description;
00621 REGISTRY_KEY *key;
00622 REGVAL_CTR *values;
00623 REGISTRY_VALUE *val;
00624 pstring path;
00625 WERROR wresult;
00626
00627
00628
00629 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
00630 wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
00631 if ( !W_ERROR_IS_OK(wresult) ) {
00632 DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
00633 path, dos_errstr(wresult)));
00634 return NULL;
00635 }
00636
00637 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
00638 DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
00639 regkey_close_internal( key );
00640 return NULL;
00641 }
00642
00643 fetch_reg_values( key, values );
00644
00645 if ( !(val = regval_ctr_getvalue( values, "Description" )) )
00646 fstrcpy( description, "Unix Service");
00647 else
00648 rpcstr_pull( description, regval_data_p(val), sizeof(description), regval_size(val), 0 );
00649
00650 regkey_close_internal( key );
00651
00652 return description;
00653 }
00654
00655
00656
00657
00658
00659 REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token )
00660 {
00661 REGISTRY_KEY *key;
00662 REGVAL_CTR *values;
00663 pstring path;
00664 WERROR wresult;
00665
00666
00667
00668 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
00669 wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
00670 if ( !W_ERROR_IS_OK(wresult) ) {
00671 DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n",
00672 path, dos_errstr(wresult)));
00673 return NULL;
00674 }
00675
00676 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
00677 DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n"));
00678 regkey_close_internal( key );
00679 return NULL;
00680 }
00681
00682 fetch_reg_values( key, values );
00683
00684 regkey_close_internal( key );
00685
00686 return values;
00687 }
00688