diff options
author | James Peach <jpeach@samba.org> | 2007-11-21 18:31:35 -0800 |
---|---|---|
committer | James Peach <jpeach@samba.org> | 2007-11-21 18:31:35 -0800 |
commit | 64b54e534008a1ac36b9ba21726ca0954fe00d63 (patch) | |
tree | 5a5e0f42c70d4afa14ba689bf4f97af321432510 /source3/services/services_db.c | |
parent | febaaae2021c2993d265cc48cf9fbef05cb4ed1b (diff) | |
parent | 7ef6c19074495110d5c0b698b05c4ee52a0744d6 (diff) | |
download | samba-64b54e534008a1ac36b9ba21726ca0954fe00d63.tar.gz samba-64b54e534008a1ac36b9ba21726ca0954fe00d63.tar.bz2 samba-64b54e534008a1ac36b9ba21726ca0954fe00d63.zip |
Merge ssh://git.samba.org/data/git/samba into v3-2-test
(This used to be commit 660ea443364e949ed06c28b00f0e1c3757f0da27)
Diffstat (limited to 'source3/services/services_db.c')
-rw-r--r-- | source3/services/services_db.c | 302 |
1 files changed, 175 insertions, 127 deletions
diff --git a/source3/services/services_db.c b/source3/services/services_db.c index ccb69d76e4..07f7aa6002 100644 --- a/source3/services/services_db.c +++ b/source3/services/services_db.c @@ -33,7 +33,7 @@ struct service_display_info { const char *description; }; -struct service_display_info builtin_svcs[] = { +struct service_display_info builtin_svcs[] = { { "Spooler", "smbd", "Print Spooler", "Internal service for spooling files to print devices" }, { "NETLOGON", "smbd", "Net Logon", "File service providing access to policy and profile data (not remotely manageable)" }, { "RemoteRegistry", "smbd", "Remote Registry Service", "Internal service providing remote access to " @@ -43,7 +43,7 @@ struct service_display_info builtin_svcs[] = { { NULL, NULL, NULL, NULL } }; -struct service_display_info common_unix_svcs[] = { +struct service_display_info common_unix_svcs[] = { { "cups", NULL, "Common Unix Printing System","Provides unified printing support for all operating systems" }, { "postfix", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" }, { "sendmail", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" }, @@ -88,27 +88,27 @@ struct service_display_info common_unix_svcs[] = { static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx ) { - SEC_ACE ace[4]; + SEC_ACE ace[4]; SEC_ACCESS mask; size_t i = 0; SEC_DESC *sd; SEC_ACL *acl; size_t sd_size; - + /* basic access for Everyone */ - + init_sec_access(&mask, SERVICE_READ_ACCESS ); init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - + init_sec_access(&mask,SERVICE_EXECUTE_ACCESS ); init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - + init_sec_access(&mask,SERVICE_ALL_ACCESS ); init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - + /* create the security descriptor */ - + if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) return NULL; @@ -127,52 +127,58 @@ static char *get_common_service_dispname( const char *servicename ) { static fstring dispname; int i; - + for ( i=0; common_unix_svcs[i].servicename; i++ ) { - if ( strequal( servicename, common_unix_svcs[i].servicename ) ) { - fstr_sprintf( dispname, "%s (%s)", + if (strequal(servicename, common_unix_svcs[i].servicename)) { + fstr_sprintf( dispname, "%s (%s)", common_unix_svcs[i].dispname, common_unix_svcs[i].servicename ); - + return dispname; } - } - + } + fstrcpy( dispname, servicename ); - + return dispname; } /******************************************************************** ********************************************************************/ -static char* cleanup_string( const char *string ) +static char *cleanup_string( const char *string ) { - pstring clean; + char *clean = NULL; char *begin, *end; + TALLOC_CTX *ctx = talloc_tos(); - pstrcpy( clean, string ); + clean = talloc_strdup(ctx, string); + if (!clean) { + return NULL; + } begin = clean; - + /* trim any beginning whilespace */ - - while ( isspace(*begin) ) + + while (isspace(*begin)) { begin++; + } - if ( *begin == '\0' ) + if (*begin == '\0') { return NULL; - + } + /* trim any trailing whitespace or carriage returns. Start at the end and move backwards */ - + end = begin + strlen(begin) - 1; - + while ( isspace(*end) || *end=='\n' || *end=='\r' ) { *end = '\0'; end--; } - return talloc_strdup(talloc_tos(), begin); + return begin; } /******************************************************************** @@ -181,50 +187,57 @@ static char* cleanup_string( const char *string ) static bool read_init_file( const char *servicename, struct rcinit_file_information **service_info ) { struct rcinit_file_information *info; - pstring filepath, str; + char *filepath = NULL; + char str[1024]; XFILE *f; char *p; - + if ( !(info = TALLOC_ZERO_P( NULL, struct rcinit_file_information ) ) ) return False; - + /* attempt the file open */ - - pstr_sprintf( filepath, "%s/%s/%s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, servicename ); - if ( !(f = x_fopen( filepath, O_RDONLY, 0 )) ) { + + filepath = talloc_asprintf(info, "%s/%s/%s", dyn_LIBDIR, + SVCCTL_SCRIPT_DIR, servicename); + if (!filepath) { + TALLOC_FREE(info); + return false; + } + if (!(f = x_fopen( filepath, O_RDONLY, 0 ))) { DEBUG(0,("read_init_file: failed to open [%s]\n", filepath)); TALLOC_FREE(info); - return False; + return false; } - + while ( (x_fgets( str, sizeof(str)-1, f )) != NULL ) { - /* ignore everything that is not a full line + /* ignore everything that is not a full line comment starting with a '#' */ - + if ( str[0] != '#' ) continue; - + /* Look for a line like '^#.*Description:' */ - + if ( (p = strstr( str, "Description:" )) != NULL ) { char *desc; p += strlen( "Description:" ) + 1; - if ( !p ) + if ( !p ) break; - + if ( (desc = cleanup_string(p)) != NULL ) info->description = talloc_strdup( info, desc ); } } - + x_fclose( f ); - + if ( !info->description ) info->description = talloc_strdup( info, "External Unix Service" ); - + *service_info = info; - + TALLOC_FREE(filepath); + return True; } @@ -237,50 +250,62 @@ static void fill_service_values( const char *name, REGVAL_CTR *values ) { UNISTR2 data, dname, ipath, description; uint32 dword; - pstring pstr; int i; - + /* These values are hardcoded in all QueryServiceConfig() replies. I'm just storing them here for cosmetic purposes */ - + dword = SVCCTL_AUTO_START; regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32)); - + dword = SVCCTL_WIN32_OWN_PROC; regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32)); dword = SVCCTL_SVC_ERROR_NORMAL; regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32)); - + /* everything runs as LocalSystem */ - + init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE ); regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2); - + /* special considerations for internal services and the DisplayName value */ - + for ( i=0; builtin_svcs[i].servicename; i++ ) { if ( strequal( name, builtin_svcs[i].servicename ) ) { - pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, builtin_svcs[i].daemon ); - init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + char *pstr = NULL; + if (asprintf(&pstr, "%s/%s/%s", + dyn_LIBDIR, SVCCTL_SCRIPT_DIR, + builtin_svcs[i].daemon) > 0) { + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + SAFE_FREE(pstr); + } else { + init_unistr2( &ipath, "", UNI_STR_TERMINATE ); + } init_unistr2( &description, builtin_svcs[i].description, UNI_STR_TERMINATE ); init_unistr2( &dname, builtin_svcs[i].dispname, UNI_STR_TERMINATE ); break; } - } - + } + /* default to an external service if we haven't found a match */ - + if ( builtin_svcs[i].servicename == NULL ) { + char *pstr = NULL; struct rcinit_file_information *init_info = NULL; - pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name ); - init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); - + if (asprintf(&pstr, "%s/%s/%s",dyn_LIBDIR, + SVCCTL_SCRIPT_DIR, name) > 0) { + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + SAFE_FREE(pstr); + } else { + init_unistr2( &ipath, "", UNI_STR_TERMINATE ); + } + /* lookup common unix display names */ init_unistr2( &dname, get_common_service_dispname( name ), UNI_STR_TERMINATE ); - /* get info from init file itself */ + /* get info from init file itself */ if ( read_init_file( name, &init_info ) ) { init_unistr2( &description, init_info->description, UNI_STR_TERMINATE ); TALLOC_FREE( init_info ); @@ -289,25 +314,25 @@ static void fill_service_values( const char *name, REGVAL_CTR *values ) init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE ); } } - + /* add the new values */ - + regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2); regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2); regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2); - + return; } /******************************************************************** ********************************************************************/ -static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, +static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, const char *name ) { REGISTRY_KEY *key_service, *key_secdesc; WERROR wresult; - pstring path; + char *path = NULL; REGVAL_CTR *values; REGSUBKEY_CTR *svc_subkeys; SEC_DESC *sd; @@ -321,15 +346,19 @@ static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, /* open the new service key */ - pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) { + return; + } wresult = regkey_open_internal( NULL, &key_service, path, get_root_nt_token(), REG_KEY_ALL ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", + DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); return; } - + SAFE_FREE(path); + /* add the 'Security' key */ if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) { @@ -337,13 +366,13 @@ static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, TALLOC_FREE( key_service ); return; } - + fetch_reg_keys( key_service, svc_subkeys ); regsubkey_ctr_addkey( svc_subkeys, "Security" ); store_reg_keys( key_service, svc_subkeys ); /* now for the service values */ - + if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) { DEBUG(0,("add_new_svc_name: talloc() failed!\n")); TALLOC_FREE( key_service ); @@ -359,15 +388,19 @@ static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" ); + if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) { + return; + } wresult = regkey_open_internal( NULL, &key_secdesc, path, get_root_nt_token(), REG_KEY_ALL ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", + DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); TALLOC_FREE( key_secdesc ); + SAFE_FREE(path); return; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) { DEBUG(0,("add_new_svc_name: talloc() failed!\n")); @@ -389,11 +422,11 @@ static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, TALLOC_FREE(key_secdesc); return; } - + regval_ctr_addvalue(values, "Security", REG_BINARY, (const char *)sd_blob.data, sd_blob.length); store_reg_values( key_secdesc, values ); - + TALLOC_FREE( key_secdesc ); return; @@ -409,35 +442,35 @@ void svcctl_init_keys( void ) REGSUBKEY_CTR *subkeys; REGISTRY_KEY *key = NULL; WERROR wresult; - + /* bad mojo here if the lookup failed. Should not happen */ - + wresult = regkey_open_internal( NULL, &key, KEY_SERVICES, get_root_nt_token(), REG_KEY_ALL ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("svcctl_init_keys: key lookup failed! (%s)\n", + DEBUG(0,("svcctl_init_keys: key lookup failed! (%s)\n", dos_errstr(wresult))); return; } - - /* lookup the available subkeys */ - + + /* lookup the available subkeys */ + if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) { DEBUG(0,("svcctl_init_keys: talloc() failed!\n")); TALLOC_FREE( key ); return; } - + fetch_reg_keys( key, subkeys ); - + /* the builting services exist */ - + for ( i=0; builtin_svcs[i].servicename; i++ ) add_new_svc_name( key, subkeys, builtin_svcs[i].servicename ); - + for ( i=0; service_list && service_list[i]; i++ ) { - + /* only add new services */ if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) ) continue; @@ -458,30 +491,34 @@ void svcctl_init_keys( void ) /******************************************************************** This is where we do the dirty work of filling in things like the - Display name, Description, etc...Always return a default secdesc + Display name, Description, etc...Always return a default secdesc in case of any failure. ********************************************************************/ -SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token ) +SEC_DESC *svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token ) { REGISTRY_KEY *key; REGVAL_CTR *values; REGISTRY_VALUE *val; SEC_DESC *ret_sd = NULL; - pstring path; + char *path= NULL; WERROR wresult; NTSTATUS status; - + /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" ); + if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) { + return NULL; + } wresult = regkey_open_internal( NULL, &key, path, token, REG_KEY_ALL ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", + DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); return NULL; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { DEBUG(0,("add_new_svc_name: talloc() failed!\n")); @@ -492,13 +529,12 @@ SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN * fetch_reg_values( key, values ); TALLOC_FREE(key); - + if ( !(val = regval_ctr_getvalue( values, "Security" )) ) { DEBUG(6,("svcctl_get_secdesc: constructing default secdesc for service [%s]\n", name)); return construct_service_sd( ctx ); } - /* stream the service security descriptor */ @@ -520,40 +556,43 @@ bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, { REGISTRY_KEY *key; WERROR wresult; - pstring path; + char *path = NULL; REGVAL_CTR *values; prs_struct ps; bool ret = False; - + /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" ); + if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) { + return false; + } wresult = regkey_open_internal( NULL, &key, path, token, REG_KEY_ALL ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", + DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); return False; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { DEBUG(0,("add_new_svc_name: talloc() failed!\n")); TALLOC_FREE( key ); return False; } - + /* stream the printer security descriptor */ - prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key, MARSHALL); - + if ( sec_io_desc("sec_desc", &sec_desc, &ps, 0 ) ) { uint32 offset = prs_offset( &ps ); regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset ); ret = store_reg_values( key, values ); } - + /* cleanup */ - + prs_mem_free( &ps ); TALLOC_FREE( key); @@ -563,25 +602,29 @@ bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, /******************************************************************** ********************************************************************/ -char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token ) +char *svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token ) { static fstring display_name; - REGISTRY_KEY *key; + REGISTRY_KEY *key = NULL; REGVAL_CTR *values; REGISTRY_VALUE *val; - pstring path; + char *path = NULL; WERROR wresult; - + /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) { + return NULL; + } wresult = regkey_open_internal( NULL, &key, path, token, REG_KEY_READ ); if ( !W_ERROR_IS_OK(wresult) ) { DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); goto fail; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n")); @@ -590,14 +633,14 @@ char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token ) } fetch_reg_values( key, values ); - + if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) ) goto fail; rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 ); TALLOC_FREE( key ); - + return display_name; fail: @@ -610,25 +653,29 @@ fail: /******************************************************************** ********************************************************************/ -char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token ) +char *svcctl_lookup_description( const char *name, NT_USER_TOKEN *token ) { static fstring description; - REGISTRY_KEY *key; + REGISTRY_KEY *key = NULL; REGVAL_CTR *values; REGISTRY_VALUE *val; - pstring path; + char *path = NULL; WERROR wresult; - + /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) { + return NULL; + } wresult = regkey_open_internal( NULL, &key, path, token, REG_KEY_READ ); if ( !W_ERROR_IS_OK(wresult) ) { DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); return NULL; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n")); @@ -637,14 +684,14 @@ char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token ) } fetch_reg_values( key, values ); - + if ( !(val = regval_ctr_getvalue( values, "Description" )) ) fstrcpy( description, "Unix Service"); else rpcstr_pull( description, regval_data_p(val), sizeof(description), regval_size(val), 0 ); TALLOC_FREE( key ); - + return description; } @@ -652,34 +699,35 @@ char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token ) /******************************************************************** ********************************************************************/ -REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token ) +REGVAL_CTR *svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token ) { - REGISTRY_KEY *key; + REGISTRY_KEY *key = NULL; REGVAL_CTR *values; - pstring path; + char *path = NULL; WERROR wresult; - + /* now add the security descriptor */ - pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) { + return NULL; + } wresult = regkey_open_internal( NULL, &key, path, token, REG_KEY_READ ); if ( !W_ERROR_IS_OK(wresult) ) { - DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n", + DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n", path, dos_errstr(wresult))); + SAFE_FREE(path); return NULL; } + SAFE_FREE(path); if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) { DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n")); TALLOC_FREE( key ); return NULL; } - fetch_reg_values( key, values ); TALLOC_FREE( key ); - return values; } - |