From 4a090ba06a54f5da179ac02bb307cc03d08831bf Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 16 Jul 2003 05:34:56 +0000 Subject: trying to get HEAD building again. If you want the code prior to this merge, checkout HEAD_PRE_3_0_0_BETA_3_MERGE (This used to be commit adb98e7b7cd0f025b52c570e4034eebf4047b1ad) --- source3/lib/charcnv.c | 45 +++++++++++++++-- source3/lib/gencache.c | 29 +++++++++-- source3/lib/module.c | 23 --------- source3/lib/popt_common.c | 4 +- source3/lib/substitute.c | 20 ++++---- source3/lib/system.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++ source3/lib/system_smbd.c | 24 +++++++-- source3/lib/time.c | 3 +- source3/lib/username.c | 76 ++++++++++++++++++---------- source3/lib/util.c | 49 +++++++++++++----- source3/lib/util_sid.c | 6 ++- source3/lib/util_sock.c | 24 +++++++-- source3/lib/util_str.c | 107 ++++++++++++++++++++++++++++++--------- source3/lib/util_unistr.c | 31 +++++++++++- source3/lib/util_uuid.c | 6 +-- source3/lib/wins_srv.c | 20 ++++++-- 16 files changed, 470 insertions(+), 122 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index eb427cc0fc..4e9c2c1592 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -55,6 +55,30 @@ static const char *charset_name(charset_t ch) else if (ch == CH_DISPLAY) ret = lp_display_charset(); else if (ch == CH_UTF8) ret = "UTF8"; +#if defined(HAVE_NL_LANGINFO) && defined(CODESET) + if (ret && strcasecmp(ret, "LOCALE") == 0) { + const char *ln = NULL; + +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + ln = nl_langinfo(CODESET); + if (ln) { + /* Check whether the charset name is supported + by iconv */ + smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE"); + if (handle == (smb_iconv_t) -1) { + DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln)); + ln = NULL; + } else { + DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln)); + smb_iconv_close(handle); + } + } + ret = ln; + } +#endif + if (!ret || !*ret) ret = "ASCII"; return ret; } @@ -363,11 +387,11 @@ size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } - if (flags & STR_TERMINATE) + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); @@ -464,7 +488,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } @@ -542,7 +566,7 @@ static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } @@ -723,8 +747,21 @@ size_t pull_utf8_allocate(void **dest, const char *src) size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) { +#ifdef DEVELOPER + /* We really need to zero fill here, not clobber + * region, as we want to ensure that valgrind thinks + * all of the outgoing buffer has been written to + * so a send() or write() won't trap an error. + * JRA. + */ +#if 0 if (dest_len != (size_t)-1) clobber_region(function, line, dest, dest_len); +#else + if (dest_len != (size_t)-1) + memset(dest, '\0', dest_len); +#endif +#endif if (!(flags & STR_ASCII) && \ ((flags & STR_UNICODE || \ diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 40b4d1390d..f3740e3e12 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -319,9 +319,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time while (node) { /* ensure null termination of the key string */ - node->node_key.dptr[node->node_key.dsize] = '\0'; - keystr = node->node_key.dptr; - + keystr = strndup(node->node_key.dptr, node->node_key.dsize); + /* * We don't use gencache_get function, because we need to iterate through * all of the entries. Validity verification is up to fn routine. @@ -329,6 +328,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time databuf = tdb_fetch(cache, node->node_key); if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) { SAFE_FREE(databuf.dptr); + SAFE_FREE(keystr); + node = node->next; continue; } entry = strndup(databuf.dptr, databuf.dsize); @@ -342,8 +343,30 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time SAFE_FREE(valstr); SAFE_FREE(entry); + SAFE_FREE(keystr); node = node->next; } tdb_search_list_free(first_node); } + +/******************************************************************** + lock a key +********************************************************************/ + +int gencache_lock_entry( const char *key ) +{ + return tdb_lock_bystring(cache, key, 0); +} + +/******************************************************************** + unlock a key +********************************************************************/ + +void gencache_unlock_entry( const char *key ) +{ + tdb_unlock_bystring(cache, key); + return; +} + + diff --git a/source3/lib/module.c b/source3/lib/module.c index 4437d085f9..ac4fe57a2c 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -130,29 +130,6 @@ void init_modules(void) } -/************************************************************************* - * This functions /path/to/foobar.so -> foobar - ************************************************************************/ -void module_path_get_name(const char *path, pstring name) -{ - char *s; - - /* First, make the path relative */ - s = strrchr(path, '/'); - if(s) pstrcpy(name, s+1); - else pstrcpy(name, path); - - if (dyn_SHLIBEXT && *dyn_SHLIBEXT && strlen(dyn_SHLIBEXT) < strlen(name)) { - int n = strlen(name) - strlen(dyn_SHLIBEXT); - - /* Remove extension if necessary */ - if (name[n-1] == '.' && !strcmp(name+n, dyn_SHLIBEXT)) { - name[n-1] = '\0'; - } - } -} - - /*************************************************************************** * This Function registers a idle event * diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index 6920ef4d5f..b8e77b2d9e 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -335,8 +335,8 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, + { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, POPT_TABLEEND }; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 7ba8648156..ac2cf687c4 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -58,7 +58,7 @@ void set_local_machine_name(const char* local_name, BOOL perm) fstrcpy(tmp_local_machine,local_name); trim_string(tmp_local_machine," "," "); - strlower(tmp_local_machine); + strlower_m(tmp_local_machine); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); } @@ -80,7 +80,7 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) fstrcpy(tmp_remote_machine,remote_name); trim_string(tmp_remote_machine," "," "); - strlower(tmp_remote_machine); + strlower_m(tmp_remote_machine); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); } @@ -111,7 +111,7 @@ void sub_set_smb_name(const char *name) fstrcpy(tmp,name); trim_string(tmp," "," "); - strlower(tmp); + strlower_m(tmp); alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1); } @@ -331,7 +331,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) switch (*(p+1)) { case 'U' : fstrcpy(tmp_str, smb_name); - strlower(tmp_str); + strlower_m(tmp_str); string_sub(p,"%U",tmp_str,l); break; case 'G' : @@ -344,7 +344,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) break; case 'D' : fstrcpy(tmp_str, current_user_info.domain); - strupper(tmp_str); + strupper_m(tmp_str); string_sub(p,"%D", tmp_str,l); break; case 'I' : @@ -357,7 +357,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) pstring temp_name; pstrcpy(temp_name, global_myname()); - strlower(temp_name); + strlower_m(temp_name); string_sub(p,"%L", temp_name,l); } break; @@ -650,7 +650,7 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, const char *connectpath, gid_t gid, const char *smb_name, - char *str) + const char *str) { char *a, *t; a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str); @@ -662,7 +662,7 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, char *alloc_sub_advanced(int snum, const char *user, const char *connectpath, gid_t gid, - const char *smb_name, char *str) + const char *smb_name, const char *str) { char *a_string, *ret_string; char *b, *p, *s, *t, *h; @@ -736,14 +736,14 @@ void standard_sub_conn(connection_struct *conn, char *str, size_t len) conn->gid, smb_user_name, str, len); } -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, char *str) +char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str) { return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, conn->connectpath, conn->gid, smb_user_name, str); } -char *alloc_sub_conn(connection_struct *conn, char *str) +char *alloc_sub_conn(connection_struct *conn, const char *str) { return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, conn->gid, smb_user_name, str); diff --git a/source3/lib/system.c b/source3/lib/system.c index 6ff97b88da..a7024c852d 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1253,3 +1253,128 @@ int sys_dup2(int oldfd, int newfd) #endif SAFE_FREE(msgbuf); } + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX also. Expand as other systems have them. +****************************************************************************/ + +ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_GETXATTR) + return getxattr(path, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_LGETXATTR) + return lgetxattr(path, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) +{ +#if defined(HAVE_FGETXATTR) + return fgetxattr(filedes, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) + return listxattr(path, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_llistxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_GETXATTR) + return llistxattr(path, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_flistxattr (int filedes, char *list, size_t size) +{ +#if defined(HAVE_FLISTXATTR) + return flistxattr(filedes, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_removexattr (const char *path, const char *name) +{ +#if defined(HAVE_REMOVEXATTR) + return removexattr(path, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lremovexattr (const char *path, const char *name) +{ +#if defined(HAVE_LREMOVEXATTR) + return lremovexattr(path, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fremovexattr (int filedes, const char *name) +{ +#if defined(HAVE_FREMOVEXATTR) + return fremovexattr(filedes, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_SETXATTR) + return setxattr(path, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_LSETXATTR) + return lsetxattr(path, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_FSETXATTR) + return fsetxattr(filedes, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index 3ae0a6395e..bcbc8c61e6 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -107,13 +107,31 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) { + char *p; + int retval; + + DEBUG(10,("sys_getgrouplist: user [%s]\n", user)); + + /* see if we should disable winbindd lookups for local users */ + if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) { + if ( !winbind_off() ) + DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n", + WINBINDD_DONT_ENV)); + else + DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n", + user)); + } + #ifdef HAVE_GETGROUPLIST - return getgrouplist(user, gid, groups, grpcnt); + retval = getgrouplist(user, gid, groups, grpcnt); #else - int retval; become_root(); retval = getgrouplist_internals(user, gid, groups, grpcnt); unbecome_root(); - return retval; #endif + + /* allow winbindd lookups */ + winbind_on(); + + return retval; } diff --git a/source3/lib/time.c b/source3/lib/time.c index f76a1bdc0d..5309711a05 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -308,7 +308,8 @@ time_t nt_time_to_unix(NTTIME *nt) time_t l_time_min = TIME_T_MIN; time_t l_time_max = TIME_T_MAX; - if (nt->high == 0) return(0); + if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) + return(0); d = ((double)nt->high)*4.0*(double)(1<<30); d += (nt->low&0xFFF00000); diff --git a/source3/lib/username.c b/source3/lib/username.c index d8f4ff80ed..98b8f33aae 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -219,7 +219,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) /* Try in all lower case first as this is the most common case on UNIX systems */ - strlower(user2); + strlower_m(user2); DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); ret = getpwnam_alloc(user2); if(ret) @@ -234,7 +234,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) } /* Try as uppercase, if username wasn't originally uppercase */ - strupper(user2); + strupper_m(user2); if(strcmp(user, user2) != 0) { DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", user2)); ret = getpwnam_alloc(user2); @@ -243,7 +243,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) } /* Try all combinations up to usernamelevel */ - strlower(user2); + strlower_m(user2); DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", lp_usernamelevel(), user2)); ret = uname_string_combinations(user2, getpwnam_alloc, lp_usernamelevel()); @@ -325,11 +325,12 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname) static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered) { - int num_groups; int i; - gid_t *groups = NULL; gid_t gid, gid_low, gid_high; BOOL ret = False; + static gid_t *groups = NULL; + static int num_groups = 0; + static fstring last_user = ""; *winbind_answered = False; @@ -349,27 +350,44 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL goto err; } - /* - * Get the gid's that this user belongs to. - */ - - if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) - return False; + /* try to user the last user we looked up */ + /* otherwise fall back to lookups */ + + if ( !strequal( last_user, user ) || !groups ) + { + /* clear any cached information */ + + SAFE_FREE(groups); + fstrcpy( last_user, "" ); + + /* + * Get the gid's that this user belongs to. + */ - if (num_groups == 0) { - *winbind_answered = True; - return False; - } + if ((num_groups = winbind_getgroups(user, &groups)) == -1) + return False; + + if ( num_groups == -1 ) + return False; - if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { - DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); - goto err; - } + if ( num_groups == 0 ) { + *winbind_answered = True; + return False; + } + + /* save the last username */ + + fstrcpy( last_user, user ); + + } + else + DEBUG(10,("user_in_winbind_group_list: using cached user groups for [%s]\n", user)); - if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { - DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ -failed with error %s\n", strerror(errno) )); - goto err; + if ( DEBUGLEVEL >= 10 ) { + DEBUG(10,("user_in_winbind_group_list: using groups -- ")); + for ( i=0; i 0) + { + dump_data(11, data, len); + } +#endif +} + char *tab_depth(int depth) { static pstring spaces; @@ -2323,8 +2347,8 @@ BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) fstrcpy(p2, pattern); fstrcpy(s2, string); - strlower(p2); - strlower(s2); + strlower_m(p2); + strlower_m(s2); return ms_fnmatch(p2, s2, Protocol) == 0; } @@ -2332,9 +2356,9 @@ BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) Recursive routine that is called by unix_wild_match. *********************************************************/ -static BOOL unix_do_match(char *regexp, char *str) +static BOOL unix_do_match(const char *regexp, const char *str) { - char *p; + const char *p; for( p = regexp; *p && *str; ) { @@ -2440,8 +2464,8 @@ BOOL unix_wild_match(const char *pattern, const char *string) pstrcpy(p2, pattern); pstrcpy(s2, string); - strlower(p2); - strlower(s2); + strlower_m(p2); + strlower_m(s2); /* Remove any *? and ** from the pattern as they are meaningless */ for(p = p2; *p; p++) @@ -2454,6 +2478,7 @@ BOOL unix_wild_match(const char *pattern, const char *string) return unix_do_match(p2, s2) == 0; } + #ifdef __INSURE__ /******************************************************************* diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 9dc0c8ca18..00f14d7d26 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -391,6 +391,9 @@ BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 * if (!exp_dom_sid || !sid || !rid) return False; + if (sid->num_auths != (exp_dom_sid->num_auths+1)) { + return False; + } if (sid_compare_domain(exp_dom_sid, sid)!=0){ *rid=(-1); @@ -642,8 +645,9 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src) if(!src) return NULL; - if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) + if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) { sid_copy( dst, src); + } return dst; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index c974050b43..1bd4c3a96b 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -654,8 +654,8 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { struct sockaddr_in sock_out; int res,ret; - int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout) / connect_loop; + int connect_loop = 10; + int increment = 10; /* create a socket to write to */ res = socket(PF_INET, type, 0); @@ -681,8 +681,13 @@ connect_again: /* Some systems return EAGAIN when they mean EINPROGRESS */ if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && loops--) { + errno == EAGAIN) && (connect_loop < timeout) ) { msleep(connect_loop); + connect_loop += increment; + if (increment < 250) { + /* After 8 rounds we end up at a max of 255 msec */ + increment *= 1.5; + } goto connect_again; } @@ -764,6 +769,19 @@ char *client_addr(void) return get_socket_addr(client_fd); } +struct in_addr *client_inaddr(struct sockaddr *sa) +{ + struct sockaddr_in *sockin = (struct sockaddr_in *) (sa); + int length = sizeof(*sa); + + if (getpeername(client_fd, sa, &length) < 0) { + DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) )); + return NULL; + } + + return &sockin->sin_addr; +} + /******************************************************************* matchname - determine if host name matches IP address. Used to confirm a hostname lookup to prevent spoof attacks diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index e561d15f61..96fbc3f124 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -38,6 +38,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) { const char *s; + char *pbuf; BOOL quoted; size_t len=1; @@ -59,17 +60,18 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) return(False); /* copy over the token */ + pbuf = buff; for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) { if (*s == '\"') { quoted = !quoted; } else { len++; - *buff++ = *s; + *pbuf++ = *s; } } *ptr = (*s) ? s+1 : s; - *buff = 0; + *pbuf = 0; return(True); } @@ -312,7 +314,7 @@ char *strupper_static(const char *s) static pstring str; pstrcpy(str, s); - strupper(str); + strupper_m(str); return str; } @@ -325,9 +327,9 @@ void strnorm(char *s) { extern int case_default; if (case_default == CASE_UPPER) - strupper(s); + strupper_m(s); else - strlower(s); + strlower_m(s); } /** @@ -1109,6 +1111,26 @@ char *strrchr_m(const char *s, char c) return (char *)(s+strlen(s2)); } +/*********************************************************************** + Return the equivalent of doing strrchr 'n' times - always going + backwards. +***********************************************************************/ + +char *strnrchr_m(const char *s, char c, unsigned int n) +{ + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strnrchr_w(ws, UCS2_CHAR(c), n); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); +} + /** Convert a string to lower case. **/ @@ -1469,6 +1491,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) #define IPSTR_LIST_SEP "," +#define IPSTR_LIST_CHAR ',' /** * Add ip string representation to ipstr list. Used also @@ -1483,19 +1506,20 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) * reallocated to new length **/ -char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) +char* ipstr_list_add(char** ipstr_list, const struct ip_service *service) { char* new_ipstr = NULL; /* arguments checking */ - if (!ipstr_list || !ip) return NULL; + if (!ipstr_list || !service) return NULL; /* attempt to convert ip to a string and append colon separator to it */ if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP, + inet_ntoa(service->ip), service->port); SAFE_FREE(*ipstr_list); } else { - asprintf(&new_ipstr, "%s", inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port); } *ipstr_list = new_ipstr; return *ipstr_list; @@ -1512,7 +1536,7 @@ char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) * @return pointer to allocated ip string **/ -char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count) +char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count) { int i; @@ -1531,7 +1555,8 @@ char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_c /** * Parse given ip string list into array of ip addresses - * (as in_addr structures) + * (as ip_service structures) + * e.g. 192.168.1.100:389,192.168.1.78, ... * * @param ipstr ip string list to be parsed * @param ip_list pointer to array of ip addresses which is @@ -1539,28 +1564,40 @@ char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_c * @return number of succesfully parsed addresses **/ -int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) +int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) { fstring token_str; - int count; + size_t count; + int i; - if (!ipstr_list || !ip_list) return 0; + if (!ipstr_list || !ip_list) + return 0; + + count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; + if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("ipstr_list_parse: malloc failed for %d entries\n", count)); + return 0; + } - for (*ip_list = NULL, count = 0; - next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); - count++) { - + for ( i=0; + next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && inode, ptr+10, 6); } -void uuid_generate_random(GUID *out) +void smb_uuid_generate_random(GUID *out) { GUID tmp; struct uuid uu; @@ -71,7 +71,7 @@ void uuid_generate_random(GUID *out) uuid_pack(&uu, out); } -char *guid_to_string(const GUID in) +char *smb_uuid_to_string(const GUID in) { struct uuid uu; char *out; @@ -87,7 +87,7 @@ char *guid_to_string(const GUID in) return out; } -const char *uuid_string_static(const GUID in) +const char *smb_uuid_string_static(const GUID in) { struct uuid uu; static char out[37]; diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c index 3372f74dcb..4a54762fde 100644 --- a/source3/lib/wins_srv.c +++ b/source3/lib/wins_srv.c @@ -70,14 +70,24 @@ static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip) { - char *keystr; + char *keystr = NULL, *wins_ip_addr = NULL, *src_ip_addr = NULL; - if (asprintf(&keystr, WINS_SRV_FMT, inet_ntoa(wins_ip), - inet_ntoa(src_ip)) == -1) { - DEBUG(0, ("wins_srv_is_dead: malloc error\n")); - return NULL; + wins_ip_addr = strdup(inet_ntoa(wins_ip)); + src_ip_addr = strdup(inet_ntoa(src_ip)); + + if ( !wins_ip_addr || !src_ip_addr ) { + DEBUG(0,("wins_srv_keystr: malloc error\n")); + goto done; } + if (asprintf(&keystr, WINS_SRV_FMT, wins_ip_addr, src_ip_addr) == -1) { + DEBUG(0, (": ns_srv_keystr: malloc error for key string\n")); + } + +done: + SAFE_FREE(wins_ip_addr); + SAFE_FREE(src_ip_addr); + return keystr; } -- cgit From 1caa6b23e417f77e7b38ecdfa47d9abe8c7b7d0e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 16 Jul 2003 05:42:34 +0000 Subject: ading new files from 3.0 (This used to be commit 99feae7b5b1c229a925367b87c0c0f636d9a2d75) --- source3/lib/smbldap.c | 1262 +++++++++++++++++++++++++++++++++++++++++++++++ source3/lib/sysquotas.c | 963 ++++++++++++++++++++++++++++++++++++ 2 files changed, 2225 insertions(+) create mode 100644 source3/lib/smbldap.c create mode 100644 source3/lib/sysquotas.c (limited to 'source3/lib') diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c new file mode 100644 index 0000000000..39c1990dec --- /dev/null +++ b/source3/lib/smbldap.c @@ -0,0 +1,1262 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Jean François Micouleau 1998 + Copyright (C) Gerald Carter 2001-2003 + Copyright (C) Shahms King 2001 + Copyright (C) Andrew Bartlett 2002-2003 + Copyright (C) Stefan (metze) Metzmacher 2002 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "smbldap.h" + +#ifndef LDAP_OPT_SUCCESS +#define LDAP_OPT_SUCCESS 0 +#endif + +/* Try not to hit the up or down server forever */ + +#define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ +#define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */ + + +/* attributes used by Samba 2.2 */ + +ATTRIB_MAP_ENTRY attrib_map_v22[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "logonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_PATH, "smbHome" }, + { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, + { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, + { LDAP_ATTR_PROFILE_PATH, "profilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "userWorkstations"}, + { LDAP_ATTR_USER_RID, "rid" }, + { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, + { LDAP_ATTR_LMPW, "lmPassword" }, + { LDAP_ATTR_NTPW, "ntPassword" }, + { LDAP_ATTR_DOMAIN, "domain" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "acctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used by Samba 3.0's sambaSamAccount */ + +ATTRIB_MAP_ENTRY attrib_map_v30[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, + { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, + { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, + { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, + { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, + { LDAP_ATTR_LMPW, "sambaLMPassword" }, + { LDAP_ATTR_NTPW, "sambaNTPassword" }, + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used for alalocating RIDs */ + +ATTRIB_MAP_ENTRY dominfo_attr_list[] = { + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_NEXT_RID, "sambaNextRid" }, + { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, + { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, + { LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL }, +}; + +/* Samba 3.0 group mapping attributes */ + +ATTRIB_MAP_ENTRY groupmap_attr_list[] = { + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { + { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* idmap_ldap sambaUnixIdPool */ + +ATTRIB_MAP_ENTRY idpool_attr_list[] = { + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY sidmap_attr_list[] = { + { LDAP_ATTR_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/********************************************************************** + perform a simple table lookup and return the attribute name + **********************************************************************/ + + const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) +{ + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + if ( table[i].attrib == key ) + return table[i].name; + i++; + } + + return NULL; +} + + +/********************************************************************** + Return the list of attribute names from a mapping table + **********************************************************************/ + + char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) +{ + char **names; + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) + i++; + i++; + + names = (char**)malloc( sizeof(char*)*i ); + if ( !names ) { + DEBUG(0,("get_attr_list: out of memory\n")); + return NULL; + } + + i = 0; + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + names[i] = strdup( table[i].name ); + i++; + } + names[i] = NULL; + + return names; +} + +/********************************************************************* + Cleanup + ********************************************************************/ + + void free_attr_list( char **list ) +{ + int i = 0; + + if ( !list ) + return; + + while ( list[i] ) { + SAFE_FREE( list[i] ); + i+=1; + } + + SAFE_FREE( list ); +} + +/******************************************************************* + find the ldap password +******************************************************************/ +BOOL fetch_ldap_pw(char **dn, char** pw) +{ + char *key = NULL; + size_t size; + + *dn = smb_xstrdup(lp_ldap_admin_dn()); + + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { + SAFE_FREE(*dn); + DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); + } + + *pw=secrets_fetch(key, &size); + SAFE_FREE(key); + + if (!size) { + /* Upgrade 2.2 style entry */ + char *p; + char* old_style_key = strdup(*dn); + char *data; + fstring old_style_pw; + + if (!old_style_key) { + DEBUG(0, ("fetch_ldap_pw: strdup failed!\n")); + return False; + } + + for (p=old_style_key; *p; p++) + if (*p == ',') *p = '/'; + + data=secrets_fetch(old_style_key, &size); + if (!size && size < sizeof(old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + + strncpy(old_style_pw, data, size); + old_style_pw[size] = 0; + + SAFE_FREE(data); + + if (!secrets_store_ldap_pw(*dn, old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + if (!secrets_delete(old_style_key)) { + DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); + } + + SAFE_FREE(old_style_key); + + *pw = smb_xstrdup(old_style_pw); + } + + return True; +} + +/******************************************************************* +search an attribute and return the first value found. +******************************************************************/ + BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + const char *attribute, pstring value) +{ + char **values; + + if ( !attribute ) + return False; + + value[0] = '\0'; + + if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { + DEBUG (10, ("smbldap_get_single_attribute: [%s] = []\n", attribute)); + + return False; + } + + if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) + { + DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", + attribute, values[0])); + ldap_value_free(values); + return False; + } + + ldap_value_free(values); +#ifdef DEBUG_PASSWORDS + DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value)); +#endif + return True; +} + +/************************************************************************ + Routine to manage the LDAPMod structure array + manage memory used by the array, by each struct, and values + ***********************************************************************/ + + void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value) +{ + LDAPMod **mods; + int i; + int j; + + mods = *modlist; + + /* sanity checks on the mod values */ + + if (attribute == NULL || *attribute == '\0') + return; +#if 0 /* commented out after discussion with abartlet. Do not reenable. + left here so other so re-add similar code --jerry */ + if (value == NULL || *value == '\0') + return; +#endif + + if (mods == NULL) + { + mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[0] = NULL; + } + + for (i = 0; mods[i] != NULL; ++i) { + if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) + break; + } + + if (mods[i] == NULL) + { + mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); + if (mods[i] == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i]->mod_op = modop; + mods[i]->mod_values = NULL; + mods[i]->mod_type = strdup(attribute); + mods[i + 1] = NULL; + } + + if (value != NULL) + { + char *utf8_value = NULL; + + j = 0; + if (mods[i]->mod_values != NULL) { + for (; mods[i]->mod_values[j] != NULL; j++); + } + mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values, + (j + 2) * sizeof (char *)); + + if (mods[i]->mod_values == NULL) { + DEBUG (0, ("make_a_mod: Memory allocation failure!\n")); + return; + } + + if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) { + DEBUG (0, ("make_a_mod: String conversion failure!\n")); + return; + } + + mods[i]->mod_values[j] = utf8_value; + + mods[i]->mod_values[j + 1] = NULL; + } + *modlist = mods; +} + + +/********************************************************************** + Set attribute to newval in LDAP, regardless of what value the + attribute had in LDAP before. +*********************************************************************/ + void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, const char *newval) +{ + char **values = NULL; + + if (existing != NULL) { + values = ldap_get_values(ldap_struct, existing, attribute); + } + + /* all of our string attributes are case insensitive */ + + if ((values != NULL) && (values[0] != NULL) && + StrCaseCmp(values[0], newval) == 0) + { + + /* Believe it or not, but LDAP will deny a delete and + an add at the same time if the values are the + same... */ + + ldap_value_free(values); + return; + } + + /* Regardless of the real operation (add or modify) + we add the new value here. We rely on deleting + the old value, should it exist. */ + + if ((newval != NULL) && (strlen(newval) > 0)) { + smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); + } + + if (values == NULL) { + /* There has been no value before, so don't delete it. + Here's a possible race: We might end up with + duplicate attributes */ + return; + } + + /* By deleting exactly the value we found in the entry this + should be race-free in the sense that the LDAP-Server will + deny the complete operation if somebody changed the + attribute behind our back. */ + + smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); + ldap_value_free(values); +} + + +/********************************************************************** + Some varients of the LDAP rebind code do not pass in the third 'arg' + pointer to a void*, so we try and work around it by assuming that the + value of the 'LDAP *' pointer is the same as the one we had passed in + **********************************************************************/ + +struct smbldap_state_lookup { + LDAP *ld; + struct smbldap_state *smbldap_state; + struct smbldap_state_lookup *prev, *next; +}; + +static struct smbldap_state_lookup *smbldap_state_lookup_list; + +static struct smbldap_state *smbldap_find_state(LDAP *ld) +{ + struct smbldap_state_lookup *t; + + for (t = smbldap_state_lookup_list; t; t = t->next) { + if (t->ld == ld) { + return t->smbldap_state; + } + } + return NULL; +} + +static void smbldap_delete_state(struct smbldap_state *smbldap_state) +{ + struct smbldap_state_lookup *t; + + for (t = smbldap_state_lookup_list; t; t = t->next) { + if (t->smbldap_state == smbldap_state) { + DLIST_REMOVE(smbldap_state_lookup_list, t); + SAFE_FREE(t); + return; + } + } +} + +static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) +{ + struct smbldap_state *tmp_ldap_state; + struct smbldap_state_lookup *t; + struct smbldap_state_lookup *tmp; + + if ((tmp_ldap_state = smbldap_find_state(ld))) { + SMB_ASSERT(tmp_ldap_state == smbldap_state); + return; + } + + t = smb_xmalloc(sizeof(*t)); + ZERO_STRUCTP(t); + + DLIST_ADD_END(smbldap_state_lookup_list, t, tmp); + t->ld = ld; + t->smbldap_state = smbldap_state; +} + +/******************************************************************* + open a connection to the ldap server. +******************************************************************/ +static int smbldap_open_connection (struct smbldap_state *ldap_state) + +{ + int rc = LDAP_SUCCESS; + int version; + BOOL ldap_v3 = False; + LDAP **ldap_struct = &ldap_state->ldap_struct; + +#ifdef HAVE_LDAP_INITIALIZE + DEBUG(10, ("smbldap_open_connection: %s\n", ldap_state->uri)); + + if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { + DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); + return rc; + } +#else + + /* Parse the string manually */ + + { + int port = 0; + fstring protocol; + fstring host; + const char *p = ldap_state->uri; + SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); + + /* skip leading "URL:" (if any) */ + if ( strncasecmp( p, "URL:", 4 ) == 0 ) { + p += 4; + } + + sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); + + if (port == 0) { + if (strequal(protocol, "ldap")) { + port = LDAP_PORT; + } else if (strequal(protocol, "ldaps")) { + port = LDAPS_PORT; + } else { + DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); + } + } + + if ((*ldap_struct = ldap_init(host, port)) == NULL) { + DEBUG(0, ("ldap_init failed !\n")); + return LDAP_OPERATIONS_ERROR; + } + + if (strequal(protocol, "ldaps")) { +#ifdef LDAP_OPT_X_TLS + int tls = LDAP_OPT_X_TLS_HARD; + if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) + { + DEBUG(0, ("Failed to setup a TLS session\n")); + } + + DEBUG(3,("LDAPS option set...!\n")); +#else + DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); + return LDAP_OPERATIONS_ERROR; +#endif + } + } +#endif + + /* Store the LDAP pointer in a lookup list */ + + smbldap_store_state(*ldap_struct, ldap_state); + + /* Upgrade to LDAPv3 if possible */ + + if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + { + if (version != LDAP_VERSION3) + { + version = LDAP_VERSION3; + if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { + ldap_v3 = True; + } + } else { + ldap_v3 = True; + } + } + + if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { +#ifdef LDAP_OPT_X_TLS + if (ldap_v3) { + if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) + { + DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", + ldap_err2string(rc))); + return rc; + } + DEBUG (3, ("StartTLS issued: using a TLS connection\n")); + } else { + + DEBUG(0, ("Need LDAPv3 for Start TLS\n")); + return LDAP_OPERATIONS_ERROR; + } +#else + DEBUG(0,("smbldap_open_connection: StartTLS not supported by LDAP client libraries!\n")); + return LDAP_OPERATIONS_ERROR; +#endif + } + + DEBUG(2, ("smbldap_open_connection: connection opened\n")); + return rc; +} + + +/******************************************************************* + a rebind function for authenticated referrals + This version takes a void* that we can shove useful stuff in :-) +******************************************************************/ +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +#else +static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, + int *methodp, int freeit, void *arg) +{ + struct smbldap_state *ldap_state = arg; + + /** @TODO Should we be doing something to check what servers we rebind to? + Could we get a referral to a machine that we don't want to give our + username and password to? */ + + if (freeit) { + SAFE_FREE(*whop); + memset(*credp, '\0', strlen(*credp)); + SAFE_FREE(*credp); + } else { + DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", + ldap_state->bind_dn)); + + *whop = strdup(ldap_state->bind_dn); + if (!*whop) { + return LDAP_NO_MEMORY; + } + *credp = strdup(ldap_state->bind_secret); + if (!*credp) { + SAFE_FREE(*whop); + return LDAP_NO_MEMORY; + } + *methodp = LDAP_AUTH_SIMPLE; + } + return 0; +} +#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + +/******************************************************************* + a rebind function for authenticated referrals + This version takes a void* that we can shove useful stuff in :-) + and actually does the connection. +******************************************************************/ +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +static int rebindproc_connect_with_state (LDAP *ldap_struct, + LDAP_CONST char *url, + ber_tag_t request, + ber_int_t msgid, void *arg) +{ + struct smbldap_state *ldap_state = arg; + int rc; + DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", + ldap_state->bind_dn)); + + /** @TODO Should we be doing something to check what servers we rebind to? + Could we get a referral to a machine that we don't want to give our + username and password to? */ + + rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); + + return rc; +} +#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + +/******************************************************************* + Add a rebind function for authenticated referrals +******************************************************************/ +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +#else +# if LDAP_SET_REBIND_PROC_ARGS == 2 +static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, + int *method, int freeit ) +{ + struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct); + + return rebindproc_with_state(ldap_struct, whop, credp, + method, freeit, ldap_state); + +} +# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ +#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + +/******************************************************************* + a rebind function for authenticated referrals + this also does the connection, but no void*. +******************************************************************/ +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +# if LDAP_SET_REBIND_PROC_ARGS == 2 +static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, + ber_int_t msgid) +{ + struct smbldap_state *ldap_state = smbldap_find_state(ld); + + return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, + ldap_state); +} +# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ +#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + +/******************************************************************* + connect to the ldap server under system privilege. +******************************************************************/ +static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct) +{ + int rc; + char *ldap_dn; + char *ldap_secret; + + /* get the password */ + if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) + { + DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); + return LDAP_INVALID_CREDENTIALS; + } + + ldap_state->bind_dn = ldap_dn; + ldap_state->bind_secret = ldap_secret; + + /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite + (OpenLDAP) doesnt' seem to support it */ + + DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", + ldap_state->uri, ldap_dn)); + +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +# if LDAP_SET_REBIND_PROC_ARGS == 2 + ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); +# endif +# if LDAP_SET_REBIND_PROC_ARGS == 3 + ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); +# endif +#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ +# if LDAP_SET_REBIND_PROC_ARGS == 2 + ldap_set_rebind_proc(ldap_struct, &rebindproc); +# endif +# if LDAP_SET_REBIND_PROC_ARGS == 3 + ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state); +# endif +#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + + rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(ldap_state->num_failures ? 2 : 0, + ("failed to bind to server with dn= %s Error: %s\n\t%s\n", + ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc), + ld_error ? ld_error : "(unknown)")); + SAFE_FREE(ld_error); + ldap_state->num_failures++; + return rc; + } + + ldap_state->num_failures = 0; + + DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); + return rc; +} + +/********************************************************************** +Connect to LDAP server (called before every ldap operation) +*********************************************************************/ +static int smbldap_open(struct smbldap_state *ldap_state) +{ + int rc; + SMB_ASSERT(ldap_state); + +#ifndef NO_LDAP_SECURITY + if (geteuid() != 0) { + DEBUG(0, ("smbldap_open: cannot access LDAP when not root..\n")); + return LDAP_INSUFFICIENT_ACCESS; + } +#endif + + if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) { + struct sockaddr_un addr; + socklen_t len = sizeof(addr); + int sd; + if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && + getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { + /* the other end has died. reopen. */ + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + ldap_state->last_ping = (time_t)0; + } else { + ldap_state->last_ping = time(NULL); + } + } + + if (ldap_state->ldap_struct != NULL) { + DEBUG(11,("smbldap_open: already connected to the LDAP server\n")); + return LDAP_SUCCESS; + } + + if ((rc = smbldap_open_connection(ldap_state))) { + return rc; + } + + if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) { + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + return rc; + } + + + ldap_state->last_ping = time(NULL); + DEBUG(4,("The LDAP server is succesful connected\n")); + + return LDAP_SUCCESS; +} + +/********************************************************************** +Disconnect from LDAP server +*********************************************************************/ +static NTSTATUS smbldap_close(struct smbldap_state *ldap_state) +{ + if (!ldap_state) + return NT_STATUS_INVALID_PARAMETER; + + if (ldap_state->ldap_struct != NULL) { + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + } + + smbldap_delete_state(ldap_state); + + DEBUG(5,("The connection to the LDAP server was closed\n")); + /* maybe free the results here --metze */ + + + + return NT_STATUS_OK; +} + +int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts) +{ + int rc; + + SMB_ASSERT(ldap_state && attempts); + + if (*attempts != 0) { + unsigned int sleep_time; + uint8 rand_byte; + + /* Sleep for a random timeout */ + rand_byte = (char)(sys_random()); + + sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; + /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds + on average. + */ + DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", + sleep_time)); + msleep(sleep_time); + } + (*attempts)++; + + if ((rc = smbldap_open(ldap_state))) { + DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts)); + return rc; + } + + return LDAP_SUCCESS; +} + + +/********************************************************************* + ********************************************************************/ + +int smbldap_search(struct smbldap_state *ldap_state, + const char *base, int scope, const char *filter, + char *attrs[], int attrsonly, + LDAPMessage **res) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_filter; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_search_s(ldap_state->ldap_struct, base, scope, + utf8_filter, attrs, attrsonly, res); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_filter); + return rc; +} + +int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_extended_operation(struct smbldap_state *ldap_state, + LDAP_CONST char *reqoid, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls, + char **retoidp, struct berval **retdatap) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + + if (!ldap_state) + return (-1); + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, + serverctrls, clientctrls, retoidp, retdatap); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + return rc; +} + +/******************************************************************* + run the search by name. +******************************************************************/ +int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, + char **search_attr, LDAPMessage ** result) +{ + int scope = LDAP_SCOPE_SUBTREE; + int rc; + + DEBUG(2, ("smbldap_search_suffix: searching for:[%s]\n", filter)); + + rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", + ld_error?ld_error:"(unknown)", ldap_err2string (rc))); + DEBUG(3,("smbldap_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(), + filter)); + SAFE_FREE(ld_error); + } + + return rc; +} + +/********************************************************************** + Housekeeping + *********************************************************************/ + +void smbldap_free_struct(struct smbldap_state **ldap_state) +{ + smbldap_close(*ldap_state); + + if ((*ldap_state)->bind_secret) { + memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret)); + } + + SAFE_FREE((*ldap_state)->bind_dn); + SAFE_FREE((*ldap_state)->bind_secret); + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + + +/********************************************************************** + Intitalise the 'general' ldap structures, on which ldap operations may be conducted + *********************************************************************/ + +NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_state **smbldap_state) +{ + *smbldap_state = talloc_zero(mem_ctx, sizeof(**smbldap_state)); + if (!*smbldap_state) { + DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (location) { + (*smbldap_state)->uri = talloc_strdup(mem_ctx, location); + } else { + (*smbldap_state)->uri = "ldap://localhost"; + } + return NT_STATUS_OK; +} + +/********************************************************************** + Add the sambaDomain to LDAP, so we don't have to search for this stuff + again. This is a once-add operation for now. + + TODO: Add other attributes, and allow modification. +*********************************************************************/ +static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, + const char *domain_name) +{ + fstring sid_string; + fstring algorithmic_rid_base_string; + pstring filter, dn; + LDAPMod **mods = NULL; + int rc; + int ldap_op; + LDAPMessage *result = NULL; + int num_result; + char **attr_list; + + slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, LDAP_OBJ_DOMINFO); + + attr_list = get_attr_list( dominfo_attr_list ); + rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) { + return NT_STATUS_UNSUCCESSFUL; + } + + num_result = ldap_count_entries(ldap_state->ldap_struct, result); + + if (num_result > 1) { + DEBUG (0, ("More than domain with that name exists: bailing out!\n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if we need to add an entry */ + DEBUG(3,("Adding new domain\n")); + ldap_op = LDAP_MOD_ADD; + + snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, lp_ldap_suffix()); + + /* Free original search */ + ldap_msgfree(result); + + /* make the changes - the entry *must* not already have samba attributes */ + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name); + + /* If we don't have an entry, then ask secrets.tdb for what it thinks. + It may choose to make it up */ + + sid_to_string(sid_string, get_global_sam_sid()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string); + + slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); + + switch(ldap_op) + { + case LDAP_MOD_ADD: + rc = smbldap_add(ldap_state, dn, mods); + break; + case LDAP_MOD_REPLACE: + rc = smbldap_modify(ldap_state, dn, mods); + break; + default: + DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (rc!=LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n", + ldap_op == LDAP_MOD_ADD ? "add" : "modify", + dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + + ldap_mods_free(mods, True); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name)); + ldap_mods_free(mods, True); + return NT_STATUS_OK; +} + +/********************************************************************** +Search for the domain info entry +*********************************************************************/ +NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, + LDAPMessage ** result, const char *domain_name, + BOOL try_add) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + pstring filter; + int rc; + char **attr_list; + int count; + + snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_DOMINFO, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name); + + DEBUG(2, ("Searching for:[%s]\n", filter)); + + + attr_list = get_attr_list( dominfo_attr_list ); + rc = smbldap_search_suffix(ldap_state, filter, attr_list , result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) { + DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); + DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); + } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) { + DEBUG(3, ("Got no domain info entries for domain\n")); + ldap_msgfree(*result); + *result = NULL; + if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) { + return smbldap_search_domain_info(ldap_state, result, domain_name, False); + } + else { + DEBUG(0, ("Adding domain info for %s failed with %s\n", + domain_name, nt_errstr(ret))); + return ret; + } + } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) { + DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", + count, domain_name)); + ldap_msgfree(*result); + *result = NULL; + return ret; + } else { + return NT_STATUS_OK; + } + + return ret; +} + diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c new file mode 100644 index 0000000000..efc9e65b9d --- /dev/null +++ b/source3/lib/sysquotas.c @@ -0,0 +1,963 @@ +/* + Unix SMB/CIFS implementation. + System QUOTA function wrappers + Copyright (C) Stefan (metze) Metzmacher 2003 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef AUTOCONF_TEST + +#include "includes.h" + +#ifdef HAVE_SYS_QUOTAS + +#if defined(HAVE_QUOTACTL_4A) +/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */ +/* this is used by: linux,HPUX,IRIX */ + +/**************************************************************************** + Abstract out the old and new Linux quota get calls. +****************************************************************************/ +static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + struct SYS_DQBLK D; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + + if (!path||!bdev||!dp) + smb_panic("sys_get_vfs_quota: called with NULL pointer"); + + ZERO_STRUCT(D); + ZERO_STRUCT(*dp); + dp->qtype = qtype; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid == 0) { + ret = 0; + break; + } + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) { + return ret; + } + + if ((D.dqb_curblocks==0)&& + (D.dqb_bsoftlimit==0)&& + (D.dqb_bhardlimit==0)) { + /* the upper layer functions don't want empty quota records...*/ + return -1; + } + + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) { + return ret; + } + + if ((D.dqb_curblocks==0)&& + (D.dqb_bsoftlimit==0)&& + (D.dqb_bhardlimit==0)) { + /* the upper layer functions don't want empty quota records...*/ + return -1; + } + + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + id.uid = getuid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) { + qflags |= QUOTAS_DENY_DISK; + } + + /* get the default quotas stored in the root's (uid =0) record */ + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) { + return ret; + } + + ret = 0; + break; + default: + errno = ENOSYS; + return -1; + } + + dp->bsize = bsize; + dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; + dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; + dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; + dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks; + + + dp->qflags = qflags; + + return ret; +} + +/**************************************************************************** + Abstract out the old and new Linux quota set calls. +****************************************************************************/ + +static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + struct SYS_DQBLK D; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + + if (!path||!bdev||!dp) + smb_panic("sys_set_vfs_quota: called with NULL pointer"); + + ZERO_STRUCT(D); + + if (bsize == dp->bsize) { + D.dqb_bsoftlimit = dp->softlimit; + D.dqb_bhardlimit = dp->hardlimit; + D.dqb_ihardlimit = dp->ihardlimit; + D.dqb_isoftlimit = dp->isoftlimit; + } else { + D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize; + D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize; + D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize; + D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize; + } + + qflags = dp->qflags; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid>0) { + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D); + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* this stuff didn't work as it should: + * switching on/off quota via quotactl() + * didn't work! + * So we only set the default limits + * --metze + * + * On HPUX we didn't have the mount path, + * we need to fix sys_path_to_bdev() + * + */ +#if 0 + uid = getuid(); + + ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, uid, (CADDR_T)&D); + + if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { + if (ret == 0) { + char *quota_file = NULL; + + asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION); + if (quota_file == NULL) { + DEBUG(0,("asprintf() failed!\n")); + errno = ENOMEM; + return -1; + } + + ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file); + } else { + ret = 0; + } + } else { + if (ret != 0) { + /* turn off */ + ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0); + } else { + ret = 0; + } + } + + DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", + ret,errno,strerror(errno),uid,bdev)); +#endif + + /* we use uid == 0 for default quotas */ + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + + break; + + default: + errno = ENOSYS; + return -1; + } + + return ret; +} + +/*#endif HAVE_QUOTACTL_4A */ +#elif defined(HAVE_QUOTACTL_4B) + +#error HAVE_QUOTACTL_4B not implemeted + +/*#endif HAVE_QUOTACTL_4B */ +#elif defined(HAVE_QUOTACTL_3) + +#error HAVE_QUOTACTL_3 not implemented + +/* #endif HAVE_QUOTACTL_3 */ +#else /* NO_QUOTACTL_USED */ + +static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + + if (!path||!bdev||!dp) + smb_panic("sys_get_vfs_quota: called with NULL pointer"); + + errno = ENOSYS; + + return ret; +} + +static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + + if (!path||!bdev||!dp) + smb_panic("sys_set_vfs_quota: called with NULL pointer"); + + errno = ENOSYS; + + return ret; +} + +#endif /* NO_QUOTACTL_USED */ + +#ifdef HAVE_MNTENT +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + SMB_STRUCT_STAT S; + FILE *fp; + struct mntent *mnt; + SMB_DEV_T devno; + + /* find the block device file */ + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + if ( sys_stat(path, &S) == -1 ) + return (-1); + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + + while ((mnt = getmntent(fp))) { + if ( sys_stat(mnt->mnt_dir,&S) == -1 ) + continue ; + + if (S.st_dev == devno) { + (*mntpath) = strdup(mnt->mnt_dir); + (*bdev) = strdup(mnt->mnt_fsname); + (*fs) = strdup(mnt->mnt_type); + if ((*mntpath)&&(*bdev)&&(*fs)) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + SAFE_FREE(*bdev); + SAFE_FREE(*fs); + ret = -1; + } + + break; + } + } + + endmntent(fp) ; + + return ret; +} +/* #endif HAVE_MNTENT */ +#elif defined(HAVE_DEVNM) + +/* we have this on HPUX, ... */ +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + char dev_disk[256]; + SMB_STRUCT_STAT S; + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + /* find the block device file */ + + if ((ret=sys_stat(path, &S))!=0) { + return ret; + } + + if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) { + return ret; + } + + /* we should get the mntpath right... + * but I don't know how + * --metze + */ + (*mntpath) = strdup(path); + (*bdev) = strdup(dev_disk); + if ((*mntpath)&&(*bdev)) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + SAFE_FREE(*bdev); + ret = -1; + } + + + return ret; +} + +/* #endif HAVE_DEVNM */ +#else +/* we should fake this up...*/ +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + (*mntpath) = strdup(path); + if (*mntpath) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + ret = -1; + } + + return ret; +} +#endif + + +/********************************************************* + if we have XFS QUOTAS we should use them + *********************************************************/ +#ifdef HAVE_XFS_QUOTA +/**************************************************************************** + Abstract out the XFS Quota Manager quota get call. +****************************************************************************/ +static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret; + uint32 qflags = 0; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; + struct fs_disk_quota D; + struct fs_quota_stat F; + ZERO_STRUCT(D); + ZERO_STRUCT(F); + + if (!bdev||!dp) + smb_panic("sys_get_xfs_quota: called with NULL pointer"); + + ZERO_STRUCT(*dp); + dp->qtype = qtype; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid == 0) { + ret = 0; + break; + } + if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) + return ret; + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) + return ret; + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* TODO: get quota status from quotactl() ... */ + if ((ret = quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F))) + return ret; + + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { + qflags |= QUOTAS_DENY_DISK; + } + else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) { + qflags |= QUOTAS_ENABLED; + } + + /* we use uid == 0 for default quotas */ + if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) + return ret; + + break; + default: + errno = ENOSYS; + return -1; + } + + dp->bsize = bsize; + dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; + dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; + dp->curinodes = (SMB_BIG_UINT)D.d_icount; + dp->curblocks = (SMB_BIG_UINT)D.d_bcount; + dp->qflags = qflags; + + return ret; +} + +/**************************************************************************** + Abstract out the XFS Quota Manager quota set call. +****************************************************************************/ +static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; + struct fs_disk_quota D; + struct fs_quota_stat F; + int q_on = 0; + int q_off = 0; + ZERO_STRUCT(D); + ZERO_STRUCT(F); + + if (!bdev||!dp) + smb_panic("sys_set_xfs_quota: called with NULL pointer"); + + if (bsize == dp->bsize) { + D.d_blk_softlimit = dp->softlimit; + D.d_blk_hardlimit = dp->hardlimit; + D.d_ino_hardlimit = dp->ihardlimit; + D.d_ino_softlimit = dp->isoftlimit; + } else { + D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize; + D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize; + D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize; + D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize; + } + + qflags = dp->qflags; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use uid == 0 for default quotas */ + if (id.uid>0) { + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D); + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* TODO */ + quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); + + if (qflags & QUOTAS_DENY_DISK) { + if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD)) + q_on |= XFS_QUOTA_UDQ_ENFD; + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } + + } else if (qflags & QUOTAS_ENABLED) { + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + + if (q_off != 0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } + + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } + } else { +#if 0 + /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! + * only swittching off XFS_QUOTA_UDQ_ACCT work + */ + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) + q_off |= XFS_QUOTA_UDQ_ACCT; + + if (q_off !=0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } +#endif + } + + /* we use uid == 0 for default quotas */ + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + break; + default: + errno = ENOSYS; + return -1; + } + + return ret; +} +#endif /* HAVE_XFS_QUOTA */ + + + + + + + + + + + + + + + +/********************************************************************* + Now the list of all filesystem specific quota systems we have found +**********************************************************************/ +static struct { + const char *name; + int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); + int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); +} sys_quota_backends[] = { +#ifdef HAVE_XFS_QUOTA + {"xfs", sys_get_xfs_quota, sys_set_xfs_quota}, +#endif /* HAVE_XFS_QUOTA */ + {NULL, NULL, NULL} +}; + +static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + const char *get_quota_command; + + get_quota_command = lp_get_quota_command(); + if (get_quota_command && *get_quota_command) { + const char *p; + char *p2; + char **lines; + pstring syscmd; + int _id = -1; + + switch(qtype) { + case SMB_USER_QUOTA_TYPE: + case SMB_USER_FS_QUOTA_TYPE: + _id = id.uid; + break; + case SMB_GROUP_QUOTA_TYPE: + case SMB_GROUP_FS_QUOTA_TYPE: + _id = id.gid; + break; + default: + DEBUG(0,("invalid quota type.\n")); + return -1; + } + + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d", + get_quota_command, path, qtype, _id); + + DEBUG (3, ("get_quota: Running command %s\n", syscmd)); + + lines = file_lines_pload(syscmd, NULL); + if (lines) { + char *line = lines[0]; + + DEBUG (3, ("Read output from get_quota, \"r%s\"\n", line)); + + /* we need to deal with long long unsigned here, if supported */ + + dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10); + p = p2; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL); + else + dp->bsize = 1024; + file_lines_free(lines); + DEBUG (3, ("Parsed output of get_quota, ...\n")); + +#ifdef LARGE_SMB_OFF_T + DEBUGADD (5,( + "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n" + "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n", + dp->qflags,(long long unsigned)dp->curblocks, + (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit, + (long long unsigned)dp->curinodes, + (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit, + (long long unsigned)dp->bsize)); +#else /* LARGE_SMB_OFF_T */ + DEBUGADD (5,( + "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n" + "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n", + dp->qflags,(long unsigned)dp->curblocks, + (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit, + (long unsigned)dp->curinodes, + (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit, + (long unsigned)dp->bsize)); +#endif /* LARGE_SMB_OFF_T */ + return 0; + } + + DEBUG (0, ("get_quota_command failed!\n")); + return -1; + } + + errno = ENOSYS; + return -1; + +invalid_param: + DEBUG(0,("The output of get_quota_command is invalid!\n")); + return -1; +} + +static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + const char *set_quota_command; + + set_quota_command = lp_set_quota_command(); + if (set_quota_command && *set_quota_command) { + char **lines; + pstring syscmd; + int _id = -1; + + switch(qtype) { + case SMB_USER_QUOTA_TYPE: + case SMB_USER_FS_QUOTA_TYPE: + _id = id.uid; + break; + case SMB_GROUP_QUOTA_TYPE: + case SMB_GROUP_FS_QUOTA_TYPE: + _id = id.gid; + break; + default: + return -1; + } + +#ifdef LARGE_SMB_OFF_T + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d " + "%u %llu %llu " + "%llu %llu %llu ", + set_quota_command, path, qtype, _id, dp->qflags, + (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit, + (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit, + (long long unsigned)dp->bsize); +#else /* LARGE_SMB_OFF_T */ + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d " + "%u %lu %lu " + "%lu %lu %lu ", + set_quota_command, path, qtype, _id, dp->qflags, + (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit, + (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit, + (long unsigned)dp->bsize); +#endif /* LARGE_SMB_OFF_T */ + + + + DEBUG (3, ("get_quota: Running command %s\n", syscmd)); + + lines = file_lines_pload(syscmd, NULL); + if (lines) { + char *line = lines[0]; + + DEBUG (3, ("Read output from set_quota, \"%s\"\n", line)); + + file_lines_free(lines); + + return 0; + } + DEBUG (0, ("set_quota_command failed!\n")); + return -1; + } + + errno = ENOSYS; + return -1; +} + +int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + int i; + BOOL ready = False; + char *mntpath = NULL; + char *bdev = NULL; + char *fs = NULL; + + if (!path||!dp) + smb_panic("sys_get_quota: called with NULL pointer"); + + if (command_get_quota(path, qtype, id, dp)==0) { + return 0; + } else if (errno != ENOSYS) { + return -1; + } + + if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + return ret; + } + + for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) { + if (strcmp(fs,sys_quota_backends[i].name)==0) { + ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp); + ready = True; + break; + } + } + + if (!ready) { + /* use the default vfs quota functions */ + ret = sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + } + + SAFE_FREE(mntpath); + SAFE_FREE(bdev); + SAFE_FREE(fs); + + if ((ret!=0)&& (errno == EDQUOT)) { + return 0; + } + + return ret; +} + +int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + int i; + BOOL ready = False; + char *mntpath = NULL; + char *bdev = NULL; + char *fs = NULL; + + /* find the block device file */ + + if (!path||!dp) + smb_panic("get_smb_quota: called with NULL pointer"); + + if (command_set_quota(path, qtype, id, dp)==0) { + return 0; + } else if (errno != ENOSYS) { + return -1; + } + + if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + return ret; + } + + for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) { + if (strcmp(fs,sys_quota_backends[i].name)==0) { + ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp); + ready = True; + break; + } + } + + if (!ready) { + /* use the default vfs quota functions */ + ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp); + } + + SAFE_FREE(mntpath); + SAFE_FREE(bdev); + SAFE_FREE(fs); + + if ((ret!=0)&& (errno == EDQUOT)) { + return 0; + } + + return ret; +} + +#else /* HAVE_SYS_QUOTAS */ + void dummy_sysquotas_c(void) +{ + return; +} +#endif /* HAVE_SYS_QUOTAS */ + +#else /* ! AUTOCONF_TEST */ +/* this is the autoconf driver to test witch quota system we should use */ + +#if defined(HAVE_QUOTACTL_4A) +/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ASM_TYPES_H +#include +#endif + +#if defined(HAVE_LINUX_QUOTA_H) +# include +# if defined(HAVE_STRUCT_IF_DQBLK) +# define SYS_DQBLK if_dqblk +# elif defined(HAVE_STRUCT_MEM_DQBLK) +# define SYS_DQBLK mem_dqblk +# endif +#elif defined(HAVE_SYS_QUOTA_H) +# include +#endif + +#ifndef SYS_DQBLK +#define SYS_DQBLK dqblk +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct SYS_DQBLK D; + + ret = quotactl(Q_GETQUOTA,"/dev/hda1",0,(void *)&D); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_4B) +/* int quotactl(const char *path, int cmd, int id, char *addr); */ + +#ifdef HAVE_SYS_QUOTA_H +#include +#else /* *BSD */ +#include +#include +#include +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct dqblk D; + + ret = quotactl("/",Q_GETQUOTA,0,(char *) &D); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_3) +/* int quotactl (char *spec, int request, char *arg); */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_QUOTA_H +#include +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct q_request request; + + ret = quotactl("/", Q_GETQUOTA, &request); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_2) + +#error HAVE_QUOTACTL_2 not implemented + +#else + +#error Unknow QUOTACTL prototype + +#endif + + int main(void) +{ + autoconf_quota(); + return 0; +} +#endif /* AUTOCONF_TEST */ -- cgit From 04bf12b176d5abe06b7f1401810369bcafe0b611 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 2 Aug 2003 20:06:57 +0000 Subject: port latest changes from SAMBA_3_0 tree (This used to be commit 3101c236b8241dc0183995ffceed551876427de4) --- source3/lib/account_pol.c | 2 +- source3/lib/charcnv.c | 120 +++++++++++++----------- source3/lib/popt_common.c | 25 ++++- source3/lib/replace.c | 18 ---- source3/lib/smbldap.c | 48 +++++++++- source3/lib/snprintf.c | 6 +- source3/lib/substitute.c | 4 +- source3/lib/sysquotas.c | 234 +++++++++++++++++++++++++++++++++++++--------- source3/lib/username.c | 4 +- source3/lib/util.c | 4 +- source3/lib/util_file.c | 4 +- source3/lib/util_sock.c | 184 ++++++++++++++++++++---------------- source3/lib/util_str.c | 67 +++++-------- source3/lib/util_unistr.c | 76 --------------- source3/lib/util_uuid.c | 2 +- 15 files changed, 462 insertions(+), 336 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index e8b382c7ab..dc131985a1 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -53,7 +53,7 @@ BOOL init_account_policy(void) account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */ account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */ account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, 0); /* don't force user to logon */ - account_policy_set(AP_MAX_PASSWORD_AGE, MAX_PASSWORD_AGE); /* 21 days */ + account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)-1); /* don't expire */ account_policy_set(AP_MIN_PASSWORD_AGE, 0); /* 0 days */ account_policy_set(AP_LOCK_ACCOUNT_DURATION, 0); /* lockout for 0 minutes */ account_policy_set(AP_RESET_COUNT_TIME, 0); /* reset immediatly */ diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 4e9c2c1592..ca5e378970 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -190,8 +190,8 @@ size_t convert_string(charset_t from, charset_t to, break; case E2BIG: reason="No more room"; - DEBUG(0, ("convert_string: Required %d, available %d\n", - srclen, destlen)); + DEBUG(0, ("convert_string: Required %lu, available %lu\n", + (unsigned long)srclen, (unsigned long)destlen)); /* we are not sure we need srclen bytes, may be more, may be less. We only know we need more than destlen @@ -319,8 +319,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, - (void **) &buffer); + size = push_ucs2_allocate(&buffer, src); if (size == -1) { smb_panic("failed to create UCS2 buffer"); } @@ -334,6 +333,33 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) return size; } +/** + strdup() a unix string to upper case. +**/ + +char *strdup_upper(const char *s) +{ + size_t size; + smb_ucs2_t *buffer; + char *out_buffer; + + size = push_ucs2_allocate(&buffer, s); + if (size == -1) { + return NULL; + } + + strupper_w(buffer); + + size = pull_ucs2_allocate(&out_buffer, buffer); + SAFE_FREE(buffer); + + if (size == -1) { + return NULL; + } + + return out_buffer; +} + size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) { size_t size; @@ -353,6 +379,32 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) return size; } +/** + strdup() a unix string to lower case. +**/ + +char *strdup_lower(const char *s) +{ + size_t size; + smb_ucs2_t *buffer; + char *out_buffer; + + size = push_ucs2_allocate(&buffer, s); + if (size == -1) { + return NULL; + } + + strlower_w(buffer); + + size = pull_ucs2_allocate(&out_buffer, buffer); + SAFE_FREE(buffer); + + if (size == -1) { + return NULL; + } + + return out_buffer; +} static size_t ucs2_align(const void *base_ptr, const void *p, int flags) { @@ -480,18 +532,11 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ { size_t len=0; size_t src_len = strlen(src); - pstring tmpbuf; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); - if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper_m(tmpbuf); - src = tmpbuf; - } - if (flags & STR_TERMINATE) src_len++; @@ -506,6 +551,18 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ dest_len &= ~1; len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len); + + if (flags & STR_UPPER) { + smb_ucs2_t *dest_ucs2 = dest; + size_t i; + for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { + smb_ucs2_t v = toupper_w(dest_ucs2[i]); + if (v != dest_ucs2[i]) { + dest_ucs2[i] = v; + } + } + } + return len; } @@ -809,44 +866,3 @@ size_t align_string(const void *base_ptr, const char *p, int flags) return 0; } -/** - Convert from unix to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_uxu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} - -/** - Convert from dos to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_dosu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index b8e77b2d9e..af1cbcfe80 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -258,19 +258,21 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) * -A,--authentication-file * -k,--use-kerberos * -N,--no-pass + * -S,--signing */ static void popt_common_credentials_callback(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, const void *data) + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) { char *p; if (reason == POPT_CALLBACK_REASON_PRE) { cmdline_auth_info.use_kerberos = False; cmdline_auth_info.got_pass = False; + cmdline_auth_info.signing_state = Undefined; pstrcpy(cmdline_auth_info.username, "GUEST"); if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); @@ -327,6 +329,22 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.got_pass = True; #endif break; + + case 'S': + { + cmdline_auth_info.signing_state = -1; + if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false")) + cmdline_auth_info.signing_state = False; + else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true")) + cmdline_auth_info.signing_state = True; + else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced")) + cmdline_auth_info.signing_state = Required; + else { + fprintf(stderr, "Unknown signing option %s\n", arg ); + exit(1); + } + } + break; } } @@ -338,5 +356,6 @@ struct poptOption popt_common_credentials[] = { { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, + { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, POPT_TABLEEND }; diff --git a/source3/lib/replace.c b/source3/lib/replace.c index 0c62ec9bfa..cd48b8d160 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -447,21 +447,3 @@ char *rep_inet_ntoa(struct in_addr ip) return t; } #endif - -#ifndef HAVE_SETENV - int setenv(const char *name, const char *value, int overwrite) -{ - char *p = NULL; - int ret = -1; - - asprintf(&p, "%s=%s", name, value); - - if (overwrite || getenv(name)) { - if (p) ret = putenv(p); - } else { - ret = 0; - } - - return ret; -} -#endif diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 39c1990dec..3f56d066ec 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -5,7 +5,7 @@ Copyright (C) Gerald Carter 2001-2003 Copyright (C) Shahms King 2001 Copyright (C) Andrew Bartlett 2002-2003 - Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Stefan (metze) Metzmacher 2002-2003 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 @@ -35,6 +35,8 @@ #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */ +#define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */ + /* attributes used by Samba 2.2 */ @@ -925,6 +927,8 @@ int smbldap_search(struct smbldap_state *ldap_state, smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_filter); return rc; } @@ -954,6 +958,8 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -983,6 +989,8 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -1012,6 +1020,8 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -1041,6 +1051,8 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + return rc; } @@ -1071,6 +1083,24 @@ int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, return rc; } +static void smbldap_idle_fn(void **data, time_t *interval, time_t now) +{ + struct smbldap_state *state = (struct smbldap_state *)(*data); + + if (state->ldap_struct == NULL) { + DEBUG(10,("ldap connection not connected...\n")); + return; + } + + if ((state->last_use+SMBLDAP_IDLE_TIME) > now) { + DEBUG(10,("ldap connection not idle...\n")); + return; + } + + DEBUG(7,("ldap connection idle...closing connection\n")); + smbldap_close(state); +} + /********************************************************************** Housekeeping *********************************************************************/ @@ -1086,6 +1116,8 @@ void smbldap_free_struct(struct smbldap_state **ldap_state) SAFE_FREE((*ldap_state)->bind_dn); SAFE_FREE((*ldap_state)->bind_secret); + smb_unregister_idle_event((*ldap_state)->event_id); + *ldap_state = NULL; /* No need to free any further, as it is talloc()ed */ @@ -1109,6 +1141,16 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_ } else { (*smbldap_state)->uri = "ldap://localhost"; } + + (*smbldap_state)->event_id = + smb_register_idle_event(smbldap_idle_fn, (void *)(*smbldap_state), + SMBLDAP_IDLE_TIME); + + if ((*smbldap_state)->event_id == SMB_EVENT_ID_INVALID) { + DEBUG(0,("Failed to register LDAP idle event!\n")); + return NT_STATUS_INVALID_HANDLE; + } + return NT_STATUS_OK; } @@ -1155,7 +1197,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, DEBUG(3,("Adding new domain\n")); ldap_op = LDAP_MOD_ADD; - snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name, lp_ldap_suffix()); /* Free original search */ @@ -1220,7 +1262,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, char **attr_list; int count; - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_DOMINFO, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name); diff --git a/source3/lib/snprintf.c b/source3/lib/snprintf.c index 9b9ceb60ca..a2f9f592db 100644 --- a/source3/lib/snprintf.c +++ b/source3/lib/snprintf.c @@ -823,12 +823,10 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) * * The logic for these two is that we need our own definition if the * OS *either* has no definition of *sprintf, or if it does have one - * that doesn't work properly according to the autoconf test. Perhaps - * these should really be smb_snprintf to avoid conflicts with buggy - * linkers? -- mbp + * that doesn't work properly according to the autoconf test. */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) - int snprintf(char *str,size_t count,const char *fmt,...) +int smb_snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index ac2cf687c4..c0d0096806 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -58,8 +58,8 @@ void set_local_machine_name(const char* local_name, BOOL perm) fstrcpy(tmp_local_machine,local_name); trim_string(tmp_local_machine," "," "); - strlower_m(tmp_local_machine); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); + strlower_m(local_machine); } /** @@ -80,8 +80,8 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) fstrcpy(tmp_remote_machine,remote_name); trim_string(tmp_remote_machine," "," "); - strlower_m(tmp_remote_machine); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); + strlower_m(remote_machine); } const char* get_remote_machine_name(void) diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c index efc9e65b9d..617f624dae 100644 --- a/source3/lib/sysquotas.c +++ b/source3/lib/sysquotas.c @@ -48,12 +48,6 @@ static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid == 0) { - ret = 0; - break; - } - if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) { return ret; } @@ -88,13 +82,19 @@ static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ qflags |= QUOTAS_DENY_DISK; } - /* get the default quotas stored in the root's (uid =0) record */ - if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) { - return ret; + ret = 0; + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + id.gid = getgid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) { + qflags |= QUOTAS_DENY_DISK; } ret = 0; break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -122,6 +122,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ { int ret = -1; uint32 qflags = 0; + uint32 oldqflags = 0; struct SYS_DQBLK D; SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; @@ -146,10 +147,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid>0) { - ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); - } + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); break; #ifdef HAVE_GROUP_QUOTA case SMB_GROUP_QUOTA_TYPE: @@ -160,7 +158,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ /* this stuff didn't work as it should: * switching on/off quota via quotactl() * didn't work! - * So we only set the default limits + * So we just return 0 * --metze * * On HPUX we didn't have the mount path, @@ -168,9 +166,9 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ * */ #if 0 - uid = getuid(); + id.uid = getuid(); - ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, uid, (CADDR_T)&D); + ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D); if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { if (ret == 0) { @@ -197,14 +195,79 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ } DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", - ret,errno,strerror(errno),uid,bdev)); + ret,errno,strerror(errno),id.uid,bdev)); +#else + id.uid = getuid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) { + oldqflags |= QUOTAS_DENY_DISK; + } + + if (oldqflags == qflags) { + ret = 0; + } else { + ret = -1; + } #endif - - /* we use uid == 0 for default quotas */ - ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); - break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + /* this stuff didn't work as it should: + * switching on/off quota via quotactl() + * didn't work! + * So we just return 0 + * --metze + * + * On HPUX we didn't have the mount path, + * we need to fix sys_path_to_bdev() + * + */ +#if 0 + id.gid = getgid(); + + ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D); + + if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { + if (ret == 0) { + char *quota_file = NULL; + + asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION); + if (quota_file == NULL) { + DEBUG(0,("asprintf() failed!\n")); + errno = ENOMEM; + return -1; + } + + ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file); + } else { + ret = 0; + } + } else { + if (ret != 0) { + /* turn off */ + ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0); + } else { + ret = 0; + } + } + + DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", + ret,errno,strerror(errno),id.gid,bdev)); +#else + id.gid = getgid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) { + oldqflags |= QUOTAS_DENY_DISK; + } + if (oldqflags == qflags) { + ret = 0; + } else { + ret = -1; + } +#endif + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -383,7 +446,7 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char ****************************************************************************/ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) { - int ret; + int ret = -1; uint32 qflags = 0; SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; struct fs_disk_quota D; @@ -399,11 +462,6 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid == 0) { - ret = 0; - break; - } if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) return ret; break; @@ -413,10 +471,8 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ return ret; break; #endif /* HAVE_GROUP_QUOTA */ - case SMB_USER_FS_QUOTA_TYPE: - /* TODO: get quota status from quotactl() ... */ - if ((ret = quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F))) - return ret; + case SMB_USER_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { qflags |= QUOTAS_DENY_DISK; @@ -425,11 +481,24 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ qflags |= QUOTAS_ENABLED; } - /* we use uid == 0 for default quotas */ - if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) - return ret; + ret = 0; break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F); + + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { + qflags |= QUOTAS_DENY_DISK; + } + else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) { + qflags |= QUOTAS_ENABLED; + } + + ret = 0; + + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -481,11 +550,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use uid == 0 for default quotas */ - if (id.uid>0) { - D.d_fieldmask |= FS_DQ_LIMIT_MASK; - ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); - } + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); break; #ifdef HAVE_GROUP_QUOTA case SMB_GROUP_QUOTA_TYPE: @@ -494,7 +560,6 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ break; #endif /* HAVE_GROUP_QUOTA */ case SMB_USER_FS_QUOTA_TYPE: - /* TODO */ quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); if (qflags & QUOTAS_DENY_DISK) { @@ -505,6 +570,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_on != 0) { ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; } } else if (qflags & QUOTAS_ENABLED) { @@ -513,6 +580,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_off != 0) { ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; } if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) @@ -520,6 +589,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_on != 0) { ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; } } else { #if 0 @@ -533,14 +604,71 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_off !=0) { ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; } +#else + ret = -1; #endif } + + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F); - /* we use uid == 0 for default quotas */ - D.d_fieldmask |= FS_DQ_LIMIT_MASK; - ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + if (qflags & QUOTAS_DENY_DISK) { + if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD)) + q_on |= XFS_QUOTA_UDQ_ENFD; + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; + } + + } else if (qflags & QUOTAS_ENABLED) { + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + + if (q_off != 0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; + } + + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; + } + } else { +#if 0 + /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! + * only swittching off XFS_QUOTA_UDQ_ACCT work + */ + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) + q_off |= XFS_QUOTA_UDQ_ACCT; + + if (q_off !=0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; + } +#else + ret = -1; +#endif + } + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -783,12 +911,17 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI } if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); return ret; } for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) { if (strcmp(fs,sys_quota_backends[i].name)==0) { ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } ready = True; break; } @@ -796,7 +929,11 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI if (!ready) { /* use the default vfs quota functions */ - ret = sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } } SAFE_FREE(mntpath); @@ -831,12 +968,17 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI } if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); return ret; } for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) { if (strcmp(fs,sys_quota_backends[i].name)==0) { ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } ready = True; break; } @@ -845,6 +987,10 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI if (!ready) { /* use the default vfs quota functions */ ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } } SAFE_FREE(mntpath); diff --git a/source3/lib/username.c b/source3/lib/username.c index 98b8f33aae..6321d47021 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -386,7 +386,7 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL if ( DEBUGLEVEL >= 10 ) { DEBUG(10,("user_in_winbind_group_list: using groups -- ")); for ( i=0; i 2003 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 @@ -2247,7 +2247,7 @@ char *pid_path(const char *name) char *lib_path(const char *name) { static pstring fname; - snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name); + fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name); return fname; } diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index 02acbd4d7e..638a6ca342 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -455,8 +455,8 @@ void *map_file(char *fname, size_t size) p = file_load(fname, &s2); if (!p) return NULL; if (s2 != size) { - DEBUG(1,("incorrect size for %s - got %d expected %d\n", - fname, s2, size)); + DEBUG(1,("incorrect size for %s - got %lu expected %lu\n", + fname, (unsigned long)s2, (unsigned long)size)); if (p) free(p); return NULL; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 1bd4c3a96b..b8b8471708 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -289,7 +289,7 @@ ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,un } /**************************************************************************** - read data from the client, reading exactly N bytes. + Read data from the client, reading exactly N bytes. ****************************************************************************/ ssize_t read_data(int fd,char *buffer,size_t N) @@ -397,7 +397,7 @@ static ssize_t write_socket_data(int fd,char *buffer,size_t N) } /**************************************************************************** -write to a socket + Write to a socket. ****************************************************************************/ ssize_t write_socket(int fd,char *buf,size_t len) @@ -416,7 +416,7 @@ ssize_t write_socket(int fd,char *buf,size_t len) } /**************************************************************************** -send a keepalive packet (rfc1002) + Send a keepalive packet (rfc1002). ****************************************************************************/ BOOL send_keepalive(int client) @@ -431,11 +431,11 @@ BOOL send_keepalive(int client) /**************************************************************************** -read 4 bytes of a smb packet and return the smb length of the packet -store the result in the buffer -This version of the function will return a length of zero on receiving -a keepalive packet. -timeout is in milliseconds. + Read 4 bytes of a smb packet and return the smb length of the packet. + Store the result in the buffer. + This version of the function will return a length of zero on receiving + a keepalive packet. + Timeout is in milliseconds. ****************************************************************************/ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout) @@ -466,10 +466,10 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int } /**************************************************************************** -read 4 bytes of a smb packet and return the smb length of the packet -store the result in the buffer. This version of the function will -never return a session keepalive (length of zero). -timeout is in milliseconds. + Read 4 bytes of a smb packet and return the smb length of the packet. + Store the result in the buffer. This version of the function will + never return a session keepalive (length of zero). + Timeout is in milliseconds. ****************************************************************************/ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) @@ -493,11 +493,10 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) } /**************************************************************************** - read an smb from a fd. Note that the buffer *MUST* be of size - BUFFER_SIZE+SAFETY_MARGIN. - The timeout is in milliseconds. - This function will return on a - receipt of a session keepalive packet. + Read an smb from a fd. Note that the buffer *MUST* be of size + BUFFER_SIZE+SAFETY_MARGIN. + The timeout is in milliseconds. + This function will return on receipt of a session keepalive packet. ****************************************************************************/ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) @@ -553,11 +552,19 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) } } + /* Check the incoming SMB signature. */ + if (!srv_check_sign_mac(buffer)) { + DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n")); + if (smb_read_error == 0) + smb_read_error = READ_BAD_SIG; + return False; + }; + return(True); } /**************************************************************************** - send an smb to a fd + Send an smb to a fd. ****************************************************************************/ BOOL send_smb(int fd,char *buffer) @@ -565,6 +572,10 @@ BOOL send_smb(int fd,char *buffer) size_t len; size_t nwritten=0; ssize_t ret; + + /* Sign the outgoing packet if required. */ + srv_calculate_sign_mac(buffer); + len = smb_len(buffer) + 4; while (nwritten < len) { @@ -647,80 +658,86 @@ int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL reb } /**************************************************************************** - create an outgoing socket. timeout is in milliseconds. - **************************************************************************/ + Create an outgoing socket. timeout is in milliseconds. +**************************************************************************/ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { - struct sockaddr_in sock_out; - int res,ret; - int connect_loop = 10; - int increment = 10; + struct sockaddr_in sock_out; + int res,ret; + int connect_loop = 10; + int increment = 10; - /* create a socket to write to */ - res = socket(PF_INET, type, 0); - if (res == -1) - { DEBUG(0,("socket error\n")); return -1; } + /* create a socket to write to */ + res = socket(PF_INET, type, 0); + if (res == -1) { + DEBUG(0,("socket error\n")); + return -1; + } - if (type != SOCK_STREAM) return(res); + if (type != SOCK_STREAM) + return(res); - memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); + memset((char *)&sock_out,'\0',sizeof(sock_out)); + putip((char *)&sock_out.sin_addr,(char *)addr); - sock_out.sin_port = htons( port ); - sock_out.sin_family = PF_INET; + sock_out.sin_port = htons( port ); + sock_out.sin_family = PF_INET; - /* set it non-blocking */ - set_blocking(res,False); + /* set it non-blocking */ + set_blocking(res,False); - DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); + DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); - /* and connect it to the destination */ -connect_again: - ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && (connect_loop < timeout) ) { - msleep(connect_loop); - connect_loop += increment; - if (increment < 250) { - /* After 8 rounds we end up at a max of 255 msec */ - increment *= 1.5; - } - goto connect_again; - } - - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); - close(res); - return -1; - } + /* and connect it to the destination */ + connect_again: + + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + /* Some systems return EAGAIN when they mean EINPROGRESS */ + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN) && (connect_loop < timeout) ) { + msleep(connect_loop); + connect_loop += increment; + if (increment < 250) { + /* After 8 rounds we end up at a max of 255 msec */ + increment *= 1.5; + } + goto connect_again; + } + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN)) { + DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); + close(res); + return -1; + } #ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; - } + + if (ret < 0 && errno == EISCONN) { + errno = 0; + ret = 0; + } #endif - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - inet_ntoa(*addr),port,strerror(errno))); - close(res); - return -1; - } + if (ret < 0) { + DEBUG(2,("error connecting to %s:%d (%s)\n", + inet_ntoa(*addr),port,strerror(errno))); + close(res); + return -1; + } - /* set it blocking again */ - set_blocking(res,True); + /* set it blocking again */ + set_blocking(res,True); - return res; + return res; } -/* - open a connected UDP socket to host on port -*/ +/**************************************************************************** + Open a connected UDP socket to host on port +**************************************************************************/ + int open_udp_socket(const char *host, int port) { int type = SOCK_DGRAM; @@ -783,9 +800,10 @@ struct in_addr *client_inaddr(struct sockaddr *sa) } /******************************************************************* - matchname - determine if host name matches IP address. Used to - confirm a hostname lookup to prevent spoof attacks - ******************************************************************/ + Matchname - determine if host name matches IP address. Used to + confirm a hostname lookup to prevent spoof attacks. +******************************************************************/ + static BOOL matchname(char *remotehost,struct in_addr addr) { struct hostent *hp; @@ -828,10 +846,10 @@ static BOOL matchname(char *remotehost,struct in_addr addr) return False; } - /******************************************************************* - return the DNS name of the remote end of a socket - ******************************************************************/ + Return the DNS name of the remote end of a socket. +******************************************************************/ + char *get_socket_name(int fd, BOOL force_lookup) { static pstring name_buf; @@ -881,8 +899,9 @@ char *get_socket_name(int fd, BOOL force_lookup) } /******************************************************************* - return the IP addr of the remote end of a socket as a string + Return the IP addr of the remote end of a socket as a string. ******************************************************************/ + char *get_socket_addr(int fd) { struct sockaddr sa; @@ -906,7 +925,6 @@ char *get_socket_addr(int fd) return addr_buf; } - /******************************************************************* Create protected unix domain socket. @@ -968,7 +986,7 @@ int create_pipe_sock(const char *socket_dir, goto out_umask; } - snprintf(path, sizeof(path), "%s/%s", socket_dir, socket_name); + pstr_sprintf(path, "%s/%s", socket_dir, socket_name); unlink(path); memset(&sunaddr, 0, sizeof(sunaddr)); diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 96fbc3f124..7569a39e6a 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -181,7 +181,9 @@ int StrCaseCmp(const char *s, const char *t) { const char * ps, * pt; - pstring buf1, buf2; + size_t size; + smb_ucs2_t *buffer_s, *buffer_t; + int ret; for (ps = s, pt = t; ; ps++, pt++) { char us, ut; @@ -206,16 +208,25 @@ int StrCaseCmp(const char *s, const char *t) return +1; } - /* TODO: Don't do this with a fixed-length buffer. This could - * still be much more efficient. */ - /* TODO: Hardcode a char-by-char comparison for UTF-8, which - * can be much faster. */ - /* TODO: Test case for this! */ - - unix_strupper(ps, strlen(ps)+1, buf1, sizeof(buf1)); - unix_strupper(pt, strlen(pt)+1, buf2, sizeof(buf2)); - - return strcmp(buf1, buf2); + size = push_ucs2_allocate(&buffer_s, s); + if (size == (size_t)-1) { + return strcmp(s, t); + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + size = push_ucs2_allocate(&buffer_t, t); + if (size == (size_t)-1) { + SAFE_FREE(buffer_s); + return strcmp(s, t); + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + ret = strcasecmp_w(buffer_s, buffer_t); + SAFE_FREE(buffer_s); + SAFE_FREE(buffer_t); + return ret; } @@ -351,7 +362,7 @@ BOOL strisnormal(const char *s) NOTE: oldc and newc must be 7 bit characters **/ -void string_replace(char *s,char oldc,char newc) +void string_replace(pstring s,char oldc,char newc) { push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); @@ -1155,21 +1166,6 @@ void strlower_m(char *s) unix_strlower(s,strlen(s)+1,s,strlen(s)+1); } -/** - Duplicate convert a string to lower case. -**/ - -char *strdup_lower(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_lower: Out of memory!\n")); - return NULL; - } - strlower_m(t); - return t; -} - /** Convert a string to upper case. **/ @@ -1194,21 +1190,6 @@ void strupper_m(char *s) unix_strupper(s,strlen(s)+1,s,strlen(s)+1); } -/** - Convert a string to upper case. -**/ - -char *strdup_upper(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_upper: Out of memory!\n")); - return NULL; - } - strupper_m(t); - return t; -} - /** Return a RFC2254 binary string representation of a buffer. Used in LDAP filters. @@ -1575,7 +1556,7 @@ int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) { - DEBUG(0,("ipstr_list_parse: malloc failed for %d entries\n", count)); + DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count)); return 0; } diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index ae000fba02..fd51f3c57d 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -759,82 +759,6 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) return NULL; } -/******************************************************************* -copy a string with max len -********************************************************************/ - -smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncpy_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -/******************************************************************* -convert and duplicate an ascii string -********************************************************************/ -smb_ucs2_t *strdup_wa(const char *src) -{ - return strndup_wa(src, 0); -} - -/* if len == 0 then duplicate the whole string */ -smb_ucs2_t *strndup_wa(const char *src, size_t len) -{ - smb_ucs2_t *dest, *s; - - s = acnv_dosu2(src); - if (!len) len = strlen_w(s); - dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t)); - if (!dest) { - DEBUG(0,("strdup_w: out of memory!\n")); - SAFE_FREE(s); - return NULL; - } - - memcpy(dest, src, len * sizeof(smb_ucs2_t)); - dest[len] = 0; - - SAFE_FREE(s); - return dest; -} - -/******************************************************************* -append a string of len bytes and add a terminator -********************************************************************/ - -smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncat_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -smb_ucs2_t *strcat_wa(smb_ucs2_t *dest, const char *src) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strcat_w(dest, ucs2_src); - SAFE_FREE(ucs2_src); - return dest; -} - BOOL trim_string_wa(smb_ucs2_t *s, const char *front, const char *back) { diff --git a/source3/lib/util_uuid.c b/source3/lib/util_uuid.c index 83553ec28e..56f0ecd85b 100644 --- a/source3/lib/util_uuid.c +++ b/source3/lib/util_uuid.c @@ -2,7 +2,7 @@ * Unix SMB/CIFS implementation. * UUID server routines * Copyright (C) Theodore Ts'o 1996, 1997, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 2002. * * 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 -- cgit From 4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 9 Sep 2003 04:07:32 +0000 Subject: sync 3.0 into HEAD for the last time (This used to be commit c17a7dc9a190156a069da3e861c18fd3f81224ad) --- source3/lib/access.c | 3 +- source3/lib/afs.c | 248 ++++++++++++++++++++++++++++++++++ source3/lib/charcnv.c | 331 +++++++++++++++++++++++++++++++++++++--------- source3/lib/dummyroot.c | 33 +++++ source3/lib/fault.c | 2 +- source3/lib/gencache.c | 9 +- source3/lib/hash.c | 15 +-- source3/lib/module.c | 30 ++++- source3/lib/ms_fnmatch.c | 82 ++++++++---- source3/lib/popt_common.c | 35 ++++- source3/lib/readline.c | 4 +- source3/lib/replace1.c | 42 ++++++ source3/lib/smbldap.c | 27 ++++ source3/lib/substitute.c | 31 +++-- source3/lib/system.c | 159 +++++++++++++++++++++- source3/lib/util.c | 81 +----------- source3/lib/util_file.c | 5 + source3/lib/util_sid.c | 2 +- source3/lib/util_str.c | 202 +++++++++++++++++++++++++--- source3/lib/version.c | 42 ++++++ 20 files changed, 1158 insertions(+), 225 deletions(-) create mode 100644 source3/lib/afs.c create mode 100644 source3/lib/dummyroot.c create mode 100644 source3/lib/replace1.c create mode 100644 source3/lib/version.c (limited to 'source3/lib') diff --git a/source3/lib/access.c b/source3/lib/access.c index c30b3c33cc..a874c8b1e2 100644 --- a/source3/lib/access.c +++ b/source3/lib/access.c @@ -281,13 +281,12 @@ static BOOL only_ipaddrs_in_list(const char** list) } if (!is_ipaddress(*list)) { - char *p; /* * if we failed, make sure that it was not because the token * was a network/netmask pair. Only network/netmask pairs * have a '/' in them */ - if ((p=strchr_m(*list, '/')) == NULL) { + if ((strchr_m(*list, '/')) == NULL) { only_ip = False; DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list)); break; diff --git a/source3/lib/afs.c b/source3/lib/afs.c new file mode 100644 index 0000000000..b96703e986 --- /dev/null +++ b/source3/lib/afs.c @@ -0,0 +1,248 @@ +/* + * Unix SMB/CIFS implementation. + * Generate AFS tickets + * Copyright (C) Volker Lendecke 2003 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#ifdef WITH_FAKE_KASERVER + +#include +#include +#include +#include +#include +#include + +_syscall5(int, afs_syscall, int, subcall, + char *, path, + int, cmd, + char *, cmarg, + int, follow); + +char *afs_cell(void) +{ + static char *cell = NULL; + + if (cell == NULL) { + cell = strdup(lp_realm()); + strlower_m(cell); + } + + return cell; +} + +struct ClearToken { + uint32 AuthHandle; + char HandShakeKey[8]; + uint32 ViceId; + uint32 BeginTimestamp; + uint32 EndTimestamp; +}; + +/* + Put an AFS token into the Kernel so that it can authenticate against + the AFS server. This assumes correct local uid settings. + + This is currently highly Linux and OpenAFS-specific. The correct API + call for this would be ktc_SetToken. But to do that we would have to + import a REALLY big bunch of libraries which I would currently like + to avoid. +*/ + +static BOOL afs_settoken(char *username, const struct ClearToken *ctok, + char *v4tkt_data, int v4tkt_length) +{ + int ret; + struct { + char *in, *out; + uint16 in_size, out_size; + } iob; + + char buf[1024]; + char *p = buf; + int tmp; + + memcpy(p, &v4tkt_length, sizeof(uint32)); + p += sizeof(uint32); + memcpy(p, v4tkt_data, v4tkt_length); + p += v4tkt_length; + + tmp = sizeof(struct ClearToken); + memcpy(p, &tmp, sizeof(uint32)); + p += sizeof(uint32); + memcpy(p, ctok, tmp); + p += tmp; + + tmp = 0; + + memcpy(p, &tmp, sizeof(uint32)); + p += sizeof(uint32); + + tmp = strlen(afs_cell()); + if (tmp >= MAXKTCREALMLEN) { + DEBUG(1, ("Realm too long\n")); + return False; + } + + strncpy(p, afs_cell(), tmp); + p += tmp; + *p = 0; + p +=1; + + iob.in = buf; + iob.in_size = PTR_DIFF(p,buf); + iob.out = buf; + iob.out_size = sizeof(buf); + +#if 0 + file_save("/tmp/ioctlbuf", iob.in, iob.in_size); +#endif + + ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0); + + DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret)); + return (ret == 0); +} + +/* + This routine takes a radical approach completely defeating the + Kerberos idea of security and using AFS simply as an intelligent + file backend. Samba has persuaded itself somehow that the user is + actually correctly identified and then we create a ticket that the + AFS server hopefully accepts using its KeyFile that the admin has + kindly stored to our secrets.tdb. + + Thanks to the book "Network Security -- PRIVATE Communication in a + PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner + Kerberos 4 tickets are not really hard to construct. + + For the comments "Alice" is the User to be auth'ed, and "Bob" is the + AFS server. */ + +BOOL afs_login(char *username) +{ + fstring ticket; + char *p = ticket; + uint32 len; + struct afs_key key; + + struct ClearToken ct; + + uint32 now; /* I assume time() returns 32 bit */ + + des_key_schedule key_schedule; + + DEBUG(10, ("Trying to log into AFS for user %s@%s\n", + username, afs_cell())); + + if (!secrets_init()) + return False; + + if (!secrets_fetch_afs_key(afs_cell(), &key)) { + DEBUG(5, ("Could not fetch AFS service key\n")); + return False; + } + + ct.AuthHandle = key.kvno; + + /* Build the ticket. This is going to be encrypted, so in our + way we fill in ct while we still have the unencrypted + form. */ + + p = ticket; + + /* The byte-order */ + *p = 1; + p += 1; + + /* "Alice", the client username */ + strncpy(p, username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, afs_cell(), sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + + ct.ViceId = getuid(); + DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); + + /* Alice's network layer address. At least Openafs-1.2.10 + ignores this, so we fill in a dummy value here. */ + SIVAL(p, 0, 0); + p += 4; + + /* We need to create a session key */ + generate_random_buffer(p, 8, False); + + /* Our client code needs the the key in the clear, it does not + know the server-key ... */ + memcpy(ct.HandShakeKey, p, 8); + + p += 8; + + /* Ticket lifetime. We fake everything here, so go as long as + possible. This is in 5-minute intervals, so 255 is 21 hours + and 15 minutes.*/ + *p = 255; + p += 1; + + /* Ticket creation time */ + now = time(NULL); + SIVAL(p, 0, now); + ct.BeginTimestamp = now; + + ct.EndTimestamp = now + (255*60*5); + if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) { + ct.BeginTimestamp += 1; /* Lifetime must be even */ + } + p += 4; + + /* And here comes Bob's name and instance, in this case the + AFS server. */ + strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + + /* And zero-pad to a multiple of 8 bytes */ + len = PTR_DIFF(p, ticket); + if (len & 7) { + uint32 extra_space = 8-(len & 7); + memset(p, 0, extra_space); + p+=extra_space; + } + len = PTR_DIFF(p, ticket); + + des_key_sched((const_des_cblock *)key.key, key_schedule); + des_pcbc_encrypt(ticket, ticket, + len, key_schedule, (C_Block *)key.key, 1); + + ZERO_STRUCT(key); + + return afs_settoken(username, &ct, ticket, len); +} + +#else + +BOOL afs_login(char *username) +{ + return True; +} + +#endif /* WITH_FAKE_KASERVER */ diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index ca5e378970..5f3cf64a68 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -40,7 +40,7 @@ static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - +static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */ /** * Return the name of a charset to give to iconv(). @@ -141,21 +141,28 @@ void init_iconv(void) /* XXX: Does this really get called every time the dos * codepage changes? */ /* XXX: Is the did_reload test too strict? */ + conv_silent = True; init_doschar_table(); init_valid_table(); + conv_silent = False; } } /** * Convert string from one encoding to another, making error checking etc + * Slow path version - uses (slow) iconv. * * @param src pointer to source string (multibyte or singlebyte) * @param srclen length of the source string in bytes * @param dest pointer to destination string (multibyte or singlebyte) * @param destlen maximal length allowed for string * @returns the number of bytes occupied in the destination + * + * Ensure the srclen contains the terminating zero. + * **/ -size_t convert_string(charset_t from, charset_t to, + +static size_t convert_string_internal(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen) { @@ -165,18 +172,14 @@ size_t convert_string(charset_t from, charset_t to, char* outbuf = (char*)dest; smb_iconv_t descriptor; - if (srclen == (size_t)-1) - srclen = strlen(src)+1; - lazy_initialize_conv(); descriptor = conv_handles[from][to]; if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { - /* conversion not supported, use as is */ - size_t len = MIN(srclen,destlen); - memcpy(dest,src,len); - return len; + if (!conv_silent) + DEBUG(0,("convert_string_internal: Conversion not supported.\n")); + goto use_as_is; } i_len=srclen; @@ -187,67 +190,208 @@ size_t convert_string(charset_t from, charset_t to, switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; case E2BIG: reason="No more room"; - DEBUG(0, ("convert_string: Required %lu, available %lu\n", - (unsigned long)srclen, (unsigned long)destlen)); + if (!conv_silent) + DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n", + (unsigned long)srclen, (unsigned long)destlen)); /* we are not sure we need srclen bytes, may be more, may be less. We only know we need more than destlen bytes ---simo */ break; case EILSEQ: - reason="Illegal multibyte sequence"; - break; + reason="Illegal multibyte sequence"; + if (!conv_silent) + DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; + default: + if (!conv_silent) + DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + break; } /* smb_panic(reason); */ } return destlen-o_len; + + use_as_is: + + /* conversion not supported, use as is */ + { + size_t len = MIN(srclen,destlen); + if (len) + memcpy(dest,src,len); + return len; + } +} + +/** + * Convert string from one encoding to another, making error checking etc + * Fast path version - handles ASCII first. + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @returns the number of bytes occupied in the destination + * + * Ensure the srclen contains the terminating zero. + * + * This function has been hand-tuned to provide a fast path. + * Don't change unless you really know what you are doing. JRA. + **/ + +size_t convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen) +{ + if (srclen == 0) + return 0; + + if (from != CH_UCS2 && to != CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + unsigned char lastp; + size_t retval = 0; + + /* If all characters are ascii, fast path here. */ + while (srclen && destlen) { + if ((lastp = *p) <= 0x7f) { + *q++ = *p++; + if (srclen != (size_t)-1) { + srclen--; + } + destlen--; + retval++; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen(p)+1; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } else if (from == CH_UCS2 && to != CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + unsigned char lastp; + + /* If all characters are ascii, fast path here. */ + while ((srclen >= 2) && destlen) { + if ((lastp = *p) <= 0x7f && p[1] == 0) { + *q++ = *p; + if (srclen != (size_t)-1) { + srclen -= 2; + } + p += 2; + destlen--; + retval++; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen_w((const void *)p)+2; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } else if (from != CH_UCS2 && to == CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + unsigned char lastp; + + /* If all characters are ascii, fast path here. */ + while (srclen && (destlen >= 2)) { + if ((lastp = *p) <= 0x7F) { + *q++ = *p++; + *q++ = '\0'; + if (srclen != (size_t)-1) { + srclen--; + } + destlen -= 2; + retval += 2; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen(p)+1; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } + return convert_string_internal(from, to, src, srclen, dest, destlen); } /** * Convert between character sets, allocating a new buffer for the result. * + * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc. * @param srclen length of source buffer. * @param dest always set at least to NULL * @note -1 is not accepted for srclen. * * @returns Size in bytes of the converted string; or -1 in case of error. + * + * Ensure the srclen contains the terminating zero. **/ -size_t convert_string_allocate(charset_t from, charset_t to, +size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest) { - size_t i_len, o_len, destlen; + size_t i_len, o_len, destlen = MAX(srclen, 512); size_t retval; const char *inbuf = (const char *)src; - char *outbuf, *ob; + char *outbuf = NULL, *ob = NULL; smb_iconv_t descriptor; *dest = NULL; if (src == NULL || srclen == (size_t)-1) return (size_t)-1; + if (srclen == 0) + return 0; lazy_initialize_conv(); descriptor = conv_handles[from][to]; if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { - /* conversion not supported, return -1*/ - DEBUG(3, ("convert_string_allocate: conversion not supported!\n")); - return -1; + if (!conv_silent) + DEBUG(0,("convert_string_allocate: Conversion not supported.\n")); + goto use_as_is; } - destlen = MAX(srclen, 512); - outbuf = NULL; convert: - destlen = destlen * 2; - ob = (char *)Realloc(outbuf, destlen); + if ((destlen*2) < destlen) { + /* wrapped ! abort. */ + if (!conv_silent) + DEBUG(0, ("convert_string_allocate: destlen wrapped !\n")); + if (!ctx) + SAFE_FREE(outbuf); + return (size_t)-1; + } else { + destlen = destlen * 2; + } + + if (ctx) + ob = (char *)talloc_realloc(ctx, ob, destlen); + else + ob = (char *)Realloc(ob, destlen); + if (!ob) { DEBUG(0, ("convert_string_allocate: realloc failed!\n")); - SAFE_FREE(outbuf); + if (!ctx) + SAFE_FREE(outbuf); return (size_t)-1; } else { outbuf = ob; @@ -262,27 +406,59 @@ convert: switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; case E2BIG: goto convert; case EILSEQ: reason="Illegal multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; } - DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); + if (!conv_silent) + DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); /* smb_panic(reason); */ return (size_t)-1; } destlen = destlen - o_len; - *dest = (char *)Realloc(ob,destlen); + if (ctx) + *dest = (char *)talloc_realloc(ctx,ob,destlen); + else + *dest = (char *)Realloc(ob,destlen); if (destlen && !*dest) { DEBUG(0, ("convert_string_allocate: out of memory!\n")); - SAFE_FREE(ob); + if (!ctx) + SAFE_FREE(ob); return (size_t)-1; } return destlen; + + use_as_is: + + /* conversion not supported, use as is */ + { + if (srclen && (destlen != srclen)) { + destlen = srclen; + if (ctx) + ob = (char *)talloc_realloc(ctx, ob, destlen); + else + ob = (char *)Realloc(ob, destlen); + if (!ob) { + DEBUG(0, ("convert_string_allocate: realloc failed!\n")); + if (!ctx) + SAFE_FREE(outbuf); + return (size_t)-1; + } + } + if (srclen && ob) + memcpy(ob,(const char *)src,srclen); + *dest = (char *)ob; + return srclen; + } } @@ -298,17 +474,12 @@ convert: static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest) { - void *alloced_string; size_t dest_len; - /* FIXME: Ridiculous to allocate two buffers and then copy the string! */ - *dest = NULL; - dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string); + dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest); if (dest_len == (size_t)-1) return (size_t)-1; - *dest = talloc_memdup(ctx, alloced_string, dest_len); - SAFE_FREE(alloced_string); if (*dest == NULL) return (size_t)-1; return dest_len; @@ -335,29 +506,49 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) /** strdup() a unix string to upper case. + Max size is pstring. **/ char *strdup_upper(const char *s) { - size_t size; - smb_ucs2_t *buffer; - char *out_buffer; - - size = push_ucs2_allocate(&buffer, s); - if (size == -1) { - return NULL; + pstring out_buffer; + const unsigned char *p = (const unsigned char *)s; + unsigned char *q = (unsigned char *)out_buffer; + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (1) { + if (*p & 0x80) + break; + *q++ = toupper(*p); + if (!*p) + break; + p++; + if (p - ( const unsigned char *)s >= sizeof(pstring)) + break; } - strupper_w(buffer); - - size = pull_ucs2_allocate(&out_buffer, buffer); - SAFE_FREE(buffer); + if (*p) { + /* MB case. */ + size_t size; + wpstring buffer; + size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer)); + if (size == -1) { + return NULL; + } - if (size == -1) { - return NULL; - } + strupper_w(buffer); - return out_buffer; + size = convert_string(CH_UCS2, CH_UNIX, buffer, sizeof(buffer), out_buffer, sizeof(out_buffer)); + if (size == -1) { + return NULL; + } + } + + return strdup(out_buffer); } size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) @@ -365,7 +556,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, + size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen, (void **) &buffer); if (size == -1) { smb_panic("failed to create UCS2 buffer"); @@ -459,6 +650,11 @@ size_t push_ascii_pstring(void *dest, const char *src) return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); } +size_t push_ascii_nstring(void *dest, const char *src) +{ + return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE); +} + /** * Copy a string from a dos codepage source to a unix char* destination. * @@ -512,6 +708,11 @@ size_t pull_ascii_fstring(char *dest, const void *src) return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE); } +size_t pull_ascii_nstring(char *dest, const void *src) +{ + return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE); +} + /** * Copy a string from a char* src to a unicode destination. * @@ -528,22 +729,26 @@ size_t pull_ascii_fstring(char *dest, const void *src) * @param dest_len is the maximum length allowed in the * destination. If dest_len is -1 then no maxiumum is used. **/ + size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) { size_t len=0; - size_t src_len = strlen(src); + size_t src_len; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); if (flags & STR_TERMINATE) - src_len++; + src_len = (size_t)-1; + else + src_len = strlen(src); if (ucs2_align(base_ptr, dest, flags)) { *(char *)dest = 0; dest = (void *)((char *)dest + 1); - if (dest_len) dest_len--; + if (dest_len) + dest_len--; len++; } @@ -599,7 +804,7 @@ size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest); } /** @@ -667,7 +872,7 @@ size_t push_utf8_allocate(char **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); } /** @@ -695,9 +900,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ } if (flags & STR_TERMINATE) { - if (src_len == (size_t)-1) { - src_len = strlen_w(src)*2 + 2; - } else { + /* src_len -1 is the default for null terminated strings. */ + if (src_len != (size_t)-1) { size_t len = strnlen_w(src, src_len/2); if (len < src_len/2) len++; @@ -755,7 +959,7 @@ size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src) { size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); *dest = NULL; - return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest); } /** @@ -785,7 +989,7 @@ size_t pull_utf8_allocate(void **dest, const char *src) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest); + return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest); } /** @@ -845,8 +1049,10 @@ size_t push_string_fn(const char *function, unsigned int line, const void *base_ size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) { +#ifdef DEVELOPER if (dest_len != (size_t)-1) clobber_region(function, line, dest, dest_len); +#endif if (!(flags & STR_ASCII) && \ ((flags & STR_UNICODE || \ @@ -865,4 +1071,3 @@ size_t align_string(const void *base_ptr, const char *p, int flags) } return 0; } - diff --git a/source3/lib/dummyroot.c b/source3/lib/dummyroot.c new file mode 100644 index 0000000000..c8465cb791 --- /dev/null +++ b/source3/lib/dummyroot.c @@ -0,0 +1,33 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Tim Potter 2003 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Stupid dummy functions required due to the horrible dependency mess + in Samba. */ + +void become_root(void) +{ + return; +} + +void unbecome_root(void) +{ + return; +} diff --git a/source3/lib/fault.c b/source3/lib/fault.c index a9e1b7bbb9..df7830ef83 100644 --- a/source3/lib/fault.c +++ b/source3/lib/fault.c @@ -34,7 +34,7 @@ static void fault_report(int sig) counter++; DEBUG(0,("===============================================================\n")); - DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),VERSION)); + DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),SAMBA_VERSION_STRING)); DEBUG(0,("\nPlease read the appendix Bugs of the Samba HOWTO collection\n")); DEBUG(0,("===============================================================\n")); diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index f3740e3e12..da8808af16 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -121,10 +121,11 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) keybuf.dsize = strlen(keystr)+1; databuf.dptr = strdup(valstr); databuf.dsize = strlen(valstr)+1; - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout \ - = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout), - (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + ret = tdb_store(cache, keybuf, databuf, 0); SAFE_FREE(valstr); SAFE_FREE(keybuf.dptr); diff --git a/source3/lib/hash.c b/source3/lib/hash.c index c7b1493b4c..18b6534dec 100644 --- a/source3/lib/hash.c +++ b/source3/lib/hash.c @@ -84,21 +84,20 @@ BOOL hash_table_init(hash_table *table, unsigned num_buckets, compare_function c * For the last few chars that cannot be int'ed, use char instead. * The function returns the bucket index number for the hashed * key. + * JRA. Use a djb-algorithm hash for speed. ************************************************************** */ static int string_hash(int hash_size, const char *key) { - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - for (value = 0x238F13AF, i=0; key[i]; i++) - value = (value + (key[i] << (i*5 % 24))); - - return (1103515243 * value + 12345) % hash_size; + u32 n = 0; + const char *p; + for (p = key; *p != '\0'; p++) { + n = ((n << 5) + n) ^ (u32)(*p); + } + return (n % hash_size); } - /* ************************************************************************* * Search the hash table for the entry in the hash chain. * The function returns the pointer to the diff --git a/source3/lib/module.c b/source3/lib/module.c index ac4fe57a2c..e2c6f6dcf5 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -23,7 +23,11 @@ #include "includes.h" #ifdef HAVE_DLOPEN -NTSTATUS smb_load_module(const char *module_name) + +/* Load a dynamic module. Only log a level 0 error if we are not checking + for the existence of a module (probling). */ + +static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) { void *handle; init_module_function *init; @@ -37,17 +41,21 @@ NTSTATUS smb_load_module(const char *module_name) handle = sys_dlopen(module_name, RTLD_LAZY); if(!handle) { - DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); + int level = is_probe ? 2 : 0; + DEBUG(level, ("Error loading module '%s': %s\n", module_name, + sys_dlerror())); + return NT_STATUS_UNSUCCESSFUL; } - init = sys_dlsym(handle, "init_module"); + init = (init_module_function *)sys_dlsym(handle, "init_module"); /* we must check sys_dlerror() to determine if it worked, because sys_dlsym() can validly return NULL */ error = sys_dlerror(); if (error) { - DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error)); + DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", + module_name, error)); return NT_STATUS_UNSUCCESSFUL; } @@ -58,6 +66,11 @@ NTSTATUS smb_load_module(const char *module_name) return status; } +NTSTATUS smb_load_module(const char *module_name) +{ + return do_smb_load_module(module_name, False); +} + /* Load all modules in list and return number of * modules that has been successfully loaded */ int smb_load_modules(const char **modules) @@ -85,8 +98,11 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module) /* if we make any 'samba multibyte string' calls here, we break for loading string modules */ + + DEBUG(5, ("Probing module '%s'\n", module)); + if (module[0] == '/') - return smb_load_module(module); + return do_smb_load_module(module, True); pstrcpy(full_path, lib_path(subsystem)); pstrcat(full_path, "/"); @@ -94,9 +110,9 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module) pstrcat(full_path, "."); pstrcat(full_path, shlib_ext()); - DEBUG(5, ("Probing module %s: Trying to load from %s\n", module, full_path)); + DEBUG(5, ("Probing module '%s': Trying to load from %s\n", module, full_path)); - return smb_load_module(full_path); + return do_smb_load_module(full_path, True); } #else /* HAVE_DLOPEN */ diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 106efa5bbc..24232c3b52 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -35,7 +35,8 @@ of the protocol. This is not yet perfect, but its a lot better than what we had */ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, - const smb_ucs2_t *string) + const smb_ucs2_t *string, + BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; @@ -61,8 +62,8 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, case UCS2_CHAR('>'): if (! *n) goto next; if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; } n++; @@ -72,13 +73,13 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, if (! *n) goto next; if (! *p) goto match; for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n == UCS2_CHAR('.') && !strchr_w(n+1,UCS2_CHAR('.'))) { n++; @@ -88,13 +89,17 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n != UCS2_CHAR('.')) goto nomatch; n++; break; default: - if (c != *n) goto nomatch; + if (case_sensitive) { + if (c != *n) goto nomatch; + } else { + if (tolower_w(c) != tolower_w(*n)) goto nomatch; + } n++; } } @@ -108,7 +113,7 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, return -1; next: - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; match: @@ -118,7 +123,8 @@ next: return 0; } -static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) +static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, + const smb_ucs2_t *string, BOOL case_sensitive) { if (!strpbrk_wa(pattern, "?*<>\"")) { smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; @@ -129,11 +135,11 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; - return ms_fnmatch_lanman_core(pattern, dotdot) && - ms_fnmatch_lanman_core(pattern, dot); + return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) && + ms_fnmatch_lanman_core(pattern, dot, case_sensitive); } - return ms_fnmatch_lanman_core(pattern, string); + return ms_fnmatch_lanman_core(pattern, string, case_sensitive); } @@ -145,13 +151,14 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin Returns 0 on match, -1 on fail. */ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int protocol) +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, + int protocol, BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; if (protocol <= PROTOCOL_LANMAN2) { - return ms_fnmatch_lanman1(pattern, string); + return ms_fnmatch_lanman1(pattern, string, case_sensitive); } while ((c = *p++)) { @@ -163,23 +170,23 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int case UCS2_CHAR('>'): if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; return -1; } - if (! *n) return ms_fnmatch_w(p, n, protocol); + if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive); n++; break; case UCS2_CHAR('*'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { n++; break; @@ -188,13 +195,17 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n != UCS2_CHAR('.')) return -1; n++; break; default: - if (c != *n) return -1; + if (case_sensitive) { + if (c != *n) return -1; + } else { + if (tolower_w(c) != tolower_w(*n)) return -1; + } n++; } } @@ -204,22 +215,35 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int return -1; } - -int ms_fnmatch(const char *pattern, const char *string, int protocol) +int ms_fnmatch(const char *pattern, const char *string, int protocol, + BOOL case_senstive) { - wpstring p, s; + wpstring buffer_pattern, buffer_string; int ret; + size_t size; + + size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } - pstrcpy_wa(p, pattern); - pstrcpy_wa(s, string); + ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive); + DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); - ret = ms_fnmatch_w(p, s, protocol); -/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ return ret; } /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { - return ms_fnmatch(pattern, string, PROTOCOL_NT1); + return ms_fnmatch(pattern, string, PROTOCOL_NT1, True); } diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index af1cbcfe80..9a5a112022 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -69,7 +69,7 @@ static void popt_common_callback(poptContext con, break; case 'V': - printf( "Version %s\n", VERSION ); + printf( "Version %s\n", SAMBA_VERSION_STRING); exit(0); break; @@ -119,6 +119,7 @@ struct poptOption popt_common_connection[] = { { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + POPT_TABLEEND }; @@ -259,6 +260,7 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) * -k,--use-kerberos * -N,--no-pass * -S,--signing + * -P --machine-pass */ @@ -335,7 +337,8 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.signing_state = -1; if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false")) cmdline_auth_info.signing_state = False; - else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true")) + else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") || + strequal(arg, "auto") ) cmdline_auth_info.signing_state = True; else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced")) cmdline_auth_info.signing_state = Required; @@ -345,6 +348,33 @@ static void popt_common_credentials_callback(poptContext con, } } break; + case 'P': + { + char *opt_password = NULL; + /* it is very useful to be able to make ads queries as the + machine account for testing purposes and for domain leave */ + + if (!secrets_init()) { + d_printf("ERROR: Unable to open secrets database\n"); + exit(1); + } + + opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + if (!opt_password) { + d_printf("ERROR: Unable to fetch machine password\n"); + exit(1); + } + pstr_sprintf(cmdline_auth_info.username, "%s$", + global_myname()); + pstrcpy(cmdline_auth_info.password,opt_password); + SAFE_FREE(opt_password); + + /* machine accounts only work with kerberos */ + cmdline_auth_info.use_kerberos = True; + cmdline_auth_info.got_pass = True; + } + break; } } @@ -357,5 +387,6 @@ struct poptOption popt_common_credentials[] = { { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, + {"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, POPT_TABLEEND }; diff --git a/source3/lib/readline.c b/source3/lib/readline.c index ceb02ef749..78b99fd7fb 100644 --- a/source3/lib/readline.c +++ b/source3/lib/readline.c @@ -51,7 +51,7 @@ ****************************************************************************/ static char *smb_readline_replacement(char *prompt, void (*callback)(void), - char **(completion_fn)(char *text, int start, int end)) + char **(completion_fn)(const char *text, int start, int end)) { fd_set fds; static pstring line; @@ -83,7 +83,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void), ****************************************************************************/ char *smb_readline(char *prompt, void (*callback)(void), - char **(completion_fn)(char *text, int start, int end)) + char **(completion_fn)(const char *text, int start, int end)) { #if HAVE_LIBREADLINE if (isatty(x_fileno(x_stdin))) { diff --git a/source3/lib/replace1.c b/source3/lib/replace1.c new file mode 100644 index 0000000000..e1be56eb12 --- /dev/null +++ b/source3/lib/replace1.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + void replace1_dummy(void); + void replace1_dummy(void) {} + +#ifndef HAVE_SETENV + int setenv(const char *name, const char *value, int overwrite) +{ + char *p = NULL; + int ret = -1; + + asprintf(&p, "%s=%s", name, value); + + if (overwrite || getenv(name)) { + if (p) ret = putenv(p); + } else { + ret = 0; + } + + return ret; +} +#endif diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 3f56d066ec..1ce03491da 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1172,6 +1172,9 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, LDAPMessage *result = NULL; int num_result; char **attr_list; + uid_t u_low, u_high; + gid_t g_low, g_high; + uint32 rid_low, rid_high; slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), @@ -1217,6 +1220,30 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), algorithmic_rid_base_string); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); + + /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set. + TODO: fix all the places where the line between idmap and normal operations + needed by smbd gets fuzzy --jerry 2003-08-11 */ + + if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high) + && get_free_rid_range(&rid_low, &rid_high) ) + { + fstring rid_str; + + fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE ); + DEBUG(10,("setting next available user rid [%s]\n", rid_str)); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), + rid_str); + + fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE ); + DEBUG(10,("setting next available group rid [%s]\n", rid_str)); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + rid_str); + + } + switch(ldap_op) { diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index c0d0096806..28466e43f2 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -57,7 +57,7 @@ void set_local_machine_name(const char* local_name, BOOL perm) already_perm = perm; fstrcpy(tmp_local_machine,local_name); - trim_string(tmp_local_machine," "," "); + trim_char(tmp_local_machine,' ',' '); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); strlower_m(local_machine); } @@ -79,7 +79,7 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) already_perm = perm; fstrcpy(tmp_remote_machine,remote_name); - trim_string(tmp_remote_machine," "," "); + trim_char(tmp_remote_machine,' ',' '); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); strlower_m(remote_machine); } @@ -98,23 +98,36 @@ const char* get_local_machine_name(void) return local_machine; } +/******************************************************************* + Setup the string used by %U substitution. +********************************************************************/ -/* - setup the string used by %U substitution -*/ void sub_set_smb_name(const char *name) { fstring tmp; /* don't let anonymous logins override the name */ - if (! *name) return; + if (! *name) + return; fstrcpy(tmp,name); - trim_string(tmp," "," "); + trim_char(tmp,' ',' '); strlower_m(tmp); alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1); } +/******************************************************************* + Setup the strings used by substitutions. Called per packet. Ensure + %U name is set correctly also. +********************************************************************/ + +void set_current_user_info(const userdom_struct *pcui) +{ + current_user_info = *pcui; + /* The following is safe as current_user_info.smb_name + * has already been sanitised in register_vuid. */ + fstrcpy(smb_user_name, current_user_info.smb_name); +} /******************************************************************* Given a pointer to a %$(NAME) expand it as an environment variable. @@ -384,7 +397,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) string_sub(p,"%m", get_remote_machine_name(),l); break; case 'v' : - string_sub(p,"%v", VERSION,l); + string_sub(p,"%v", SAMBA_VERSION_STRING,l); break; case '$' : p += expand_env_var(p,l); @@ -539,7 +552,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) t = realloc_string_sub(t, "%m", remote_machine); break; case 'v' : - t = realloc_string_sub(t, "%v", VERSION); + t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING); break; case '$' : t = realloc_expand_env_var(t, p); /* Expand environment variables */ diff --git a/source3/lib/system.c b/source3/lib/system.c index a7024c852d..b020a20373 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1263,6 +1263,16 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si { #if defined(HAVE_GETXATTR) return getxattr(path, name, value, size); +#elif defined(HAVE_ATTR_GET) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; @@ -1273,6 +1283,16 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s { #if defined(HAVE_LGETXATTR) return lgetxattr(path, name, value, size); +#elif defined(HAVE_ATTR_GET) + int retval, flags = ATTR_DONTFOLLOW; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; @@ -1283,16 +1303,96 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) { #if defined(HAVE_FGETXATTR) return fgetxattr(filedes, name, value, size); +#elif defined(HAVE_ATTR_GETF) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; #endif } +#if defined(HAVE_ATTR_LIST) +static char attr_buffer[ATTR_MAX_VALUELEN]; + +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) +{ + int retval = 0, index; + attrlist_cursor_t *cursor = 0; + int total_size = 0; + attrlist_t * al = (attrlist_t *)attr_buffer; + attrlist_ent_t *ae; + size_t ent_size, left = size; + char *bp = list; + + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("user."); + if (left >= ent_size) { + strncpy(bp, "user.", sizeof("user.")); + strncat(bp, ae->a_name, ent_size - sizeof("user.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + if (retval == 0) { + flags |= ATTR_ROOT; + cursor = 0; + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("system."); + if (left >= ent_size) { + strncpy(bp, "system.", sizeof("system.")); + strncat(bp, ae->a_name, ent_size - sizeof("system.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + } + return (ssize_t)(retval ? retval : total_size); +} + +#endif + ssize_t sys_listxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LISTXATTR) return listxattr(path, list, size); +#elif defined(HAVE_ATTR_LIST) + return irix_attr_list(path, 0, list, size, 0); #else errno = ENOSYS; return -1; @@ -1301,8 +1401,10 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size) ssize_t sys_llistxattr (const char *path, char *list, size_t size) { -#if defined(HAVE_GETXATTR) +#if defined(HAVE_LLISTXATTR) return llistxattr(path, list, size); +#elif defined(HAVE_ATTR_LIST) + return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); #else errno = ENOSYS; return -1; @@ -1313,6 +1415,8 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size) { #if defined(HAVE_FLISTXATTR) return flistxattr(filedes, list, size); +#elif defined(HAVE_ATTR_LISTF) + return irix_attr_list(NULL, filedes, list, size, 0); #else errno = ENOSYS; return -1; @@ -1323,6 +1427,13 @@ int sys_removexattr (const char *path, const char *name) { #if defined(HAVE_REMOVEXATTR) return removexattr(path, name); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); #else errno = ENOSYS; return -1; @@ -1333,6 +1444,13 @@ int sys_lremovexattr (const char *path, const char *name) { #if defined(HAVE_LREMOVEXATTR) return lremovexattr(path, name); +#elif defined(HAVE_ATTR_REMOVE) + int flags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); #else errno = ENOSYS; return -1; @@ -1343,16 +1461,37 @@ int sys_fremovexattr (int filedes, const char *name) { #if defined(HAVE_FREMOVEXATTR) return fremovexattr(filedes, name); +#elif defined(HAVE_ATTR_REMOVEF) + int flags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_removef(filedes, attrname, flags); #else errno = ENOSYS; return -1; #endif } +#if !defined(HAVE_SETXATTR) +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#endif + int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) { #if defined(HAVE_SETXATTR) return setxattr(path, name, value, size, flags); +#elif defined(HAVE_ATTR_SET) + int myflags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; @@ -1363,6 +1502,15 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t { #if defined(HAVE_LSETXATTR) return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_ATTR_SET) + int myflags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; @@ -1373,6 +1521,15 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size { #if defined(HAVE_FSETXATTR) return fsetxattr(filedes, name, value, size, flags); +#elif defined(HAVE_ATTR_SETF) + int myflags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_setf(filedes, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; diff --git a/source3/lib/util.c b/source3/lib/util.c index eaa232a549..766c5041b4 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -261,7 +261,7 @@ BOOL init_names(void) } fstrcpy( local_machine, global_myname() ); - trim_string( local_machine, " ", " " ); + trim_char( local_machine, ' ', ' ' ); p = strchr( local_machine, ' ' ); if (p) *p = 0; @@ -311,7 +311,7 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) static const char *Atoic(const char *p, int *n, const char *c) { - if (!isdigit((const int)*p)) { + if (!isdigit((int)*p)) { DEBUG(5, ("Atoic: malformed number\n")); return NULL; } @@ -605,68 +605,6 @@ void unix_clean_name(char *s) trim_string(s,NULL,"/.."); } -/******************************************************************* - Convert '\' to '/'. - Reduce a file name, removing or reducing /../ , /./ , // elements. - Remove also any trailing . and / - Return a new allocated string. -********************************************************************/ - -smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s) -{ - smb_ucs2_t *ns; - smb_ucs2_t *p, *r, *t; - - DEBUG(3, ("unix_clean_path\n")); /* [%unicode]\n")); */ - if(!s) - return NULL; - - /* convert '\' to '/' */ - ns = strdup_w(s); - if (!ns) - return NULL; - unix_format_w(ns); - - /* remove all double slashes */ - p = ns; - ns = all_string_sub_wa(p, "//", "/"); - SAFE_FREE(p); - if (!ns) - return NULL; - - /* remove any /./ */ - p = ns; - ns = all_string_sub_wa(p, "/./", "/"); - SAFE_FREE(p); - if (!ns) - return NULL; - - /* reduce any /../ */ - t = ns; - while (*t && (r = strstr_wa(t, "/.."))) { - t = &(r[3]); - if (*t == UCS2_CHAR('/') || *t == 0) { - *r = 0; - p = strrchr_w(ns, UCS2_CHAR('/')); - if (!p) - p = ns; - if (*t == 0) - *p = 0; - else - memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t)); - t = p; - } - } - - /* remove any leading ./ trailing /. */ - trim_string_wa(ns, "./", "/."); - - /* remove any leading and trailing / */ - trim_string_wa(ns, "/", "/"); - - return ns; -} - /**************************************************************************** Make a dir struct. ****************************************************************************/ @@ -2205,7 +2143,7 @@ char *lock_path(const char *name) static pstring fname; pstrcpy(fname,lp_lockdir()); - trim_string(fname,"","/"); + trim_char(fname,'\0','/'); if (!directory_exist(fname,NULL)) mkdir(fname,0755); @@ -2225,7 +2163,7 @@ char *pid_path(const char *name) static pstring fname; pstrcpy(fname,lp_piddir()); - trim_string(fname,"","/"); + trim_char(fname,'\0','/'); if (!directory_exist(fname,NULL)) mkdir(fname,0755); @@ -2335,21 +2273,12 @@ BOOL ms_has_wild_w(const smb_ucs2_t *s) BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) { - fstring p2, s2; - if (strcmp(string,"..") == 0) string = "."; if (strcmp(pattern,".") == 0) return False; - if (is_case_sensitive) - return ms_fnmatch(pattern, string, Protocol) == 0; - - fstrcpy(p2, pattern); - fstrcpy(s2, string); - strlower_m(p2); - strlower_m(s2); - return ms_fnmatch(p2, s2, Protocol) == 0; + return ms_fnmatch(pattern, string, Protocol, is_case_sensitive) == 0; } /********************************************************* diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index 638a6ca342..bd505ac921 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -20,6 +20,11 @@ #include "includes.h" +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + + static int gotalarm; /*************************************************************** diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 00f14d7d26..fbb393770d 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -93,7 +93,7 @@ static const struct { {SID_NAME_UNKNOWN, "UNKNOWN"}, {SID_NAME_COMPUTER, "Computer"}, - {0, NULL} + {(enum SID_NAME_USE)0, NULL} }; const char *sid_type_lookup(uint32 sid_type) diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 7569a39e6a..82b312e241 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -37,7 +37,7 @@ **/ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) { - const char *s; + char *s; char *pbuf; BOOL quoted; size_t len=1; @@ -45,7 +45,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) if (!ptr) return(False); - s = *ptr; + s = (char *)*ptr; /* default to simple separators */ if (!sep) @@ -88,7 +88,7 @@ BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize) { BOOL ret; if (!ptr) - ptr = (const char **)&last_ptr; + ptr = &last_ptr; ret = next_token(ptr, buff, sep, bufsize); last_ptr = *ptr; @@ -109,7 +109,7 @@ void set_first_token(char *ptr) char **toktocliplist(int *ctok, const char *sep) { - char *s=last_ptr; + char *s=(char *)last_ptr; int ictok=0; char **ret, **iret; @@ -132,7 +132,7 @@ char **toktocliplist(int *ctok, const char *sep) } while(*s); *ctok=ictok; - s=last_ptr; + s=(char *)last_ptr; if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL; @@ -364,9 +364,27 @@ BOOL strisnormal(const char *s) void string_replace(pstring s,char oldc,char newc) { - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + unsigned char *p; + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + for (p = (unsigned char *)s; *p; p++) { + if (*p & 0x80) /* mb string - slow path. */ + break; + if (*p == oldc) + *p = newc; + } + + if (!*p) + return; + + /* Slow (mb) path. */ + push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); + pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); } /** @@ -406,6 +424,59 @@ size_t str_ascii_charnum(const char *s) return strlen(tmpbuf2); } +BOOL trim_char(char *s,char cfront,char cback) +{ + BOOL ret = False; + char *ep; + char *fp = s; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) + return False; + + if (cfront) { + while (*fp && *fp == cfront) + fp++; + if (!*fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + if (fp != s) + ret = True; + } + + ep = fp + strlen(fp) - 1; + if (cback) { + /* Attempt ascii only. Bail for mb strings. */ + while ((ep >= fp) && (*ep == cback)) { + ret = True; + if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) { + /* Could be mb... bail back to tim_string. */ + char fs[2], bs[2]; + if (cfront) { + fs[0] = cfront; + fs[1] = '\0'; + } + bs[0] = cback; + bs[1] = '\0'; + return trim_string(s, cfront ? fs : NULL, bs); + } else { + ep--; + } + } + if (ep < fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + } + + ep[1] = '\0'; + memmove(s, fp, ep-fp+2); + return ret; +} + /** Trim the specified elements off the front and back of a string. **/ @@ -428,7 +499,9 @@ BOOL trim_string(char *s,const char *front,const char *back) if (front_len) { while (len && strncmp(s, front, front_len)==0) { - memcpy(s, s+front_len, (len-front_len)+1); + /* Must use memmove here as src & dest can + * easily overlap. Found by valgrind. JRA. */ + memmove(s, s+front_len, (len-front_len)+1); len -= front_len; ret=True; } @@ -501,7 +574,9 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_ return NULL; } +#ifdef DEVELOPER clobber_region(fn,line,dest, maxlength+1); +#endif if (!src) { *dest = 0; @@ -540,7 +615,9 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size src_len = strnlen(src, maxlength + 1); dest_len = strnlen(dest, maxlength + 1); +#ifdef DEVELOPER clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len); +#endif if (src_len + dest_len > maxlength) { DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", @@ -567,7 +644,9 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con { size_t len, i; +#ifdef DEVELOPER clobber_region(fn, line, dest, maxlength); +#endif if (!dest) { DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n")); @@ -607,7 +686,9 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n) { char *d = dest; +#ifdef DEVELOPER clobber_region(fn, line, dest, n+1); +#endif if (!dest) return(NULL); @@ -637,8 +718,9 @@ static char *strncpyn(char *dest, const char *src, size_t n, char c) char *p; size_t str_len; +#ifdef DEVELOPER clobber_region(dest, n+1); - +#endif p = strchr_m(src, c); if (p == NULL) { DEBUG(5, ("strncpyn: separator character (%c) not found\n", c)); @@ -910,6 +992,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert) while ((p = strstr(s,pattern))) { if (ld > 0) { + int offset = PTR_DIFF(s,string); char *t = Realloc(string, ls + ld + 1); if (!t) { DEBUG(0, ("realloc_string_sub: out of memory!\n")); @@ -917,7 +1000,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert) return NULL; } string = t; - p = t + (p - s); + p = t + offset + (p - s); } if (li != lp) { memmove(p+li,p+lp,strlen(p+lp)+1); @@ -1098,6 +1181,19 @@ char *strchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (*s && (((unsigned char)s[0]) & 0x80)) { + if (*s == c) + return s; + } + + if (!*s) + return NULL; + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) @@ -1109,17 +1205,53 @@ char *strchr_m(const char *s, char c) char *strrchr_m(const char *s, char c) { - wpstring ws; - pstring s2; - smb_ucs2_t *p; + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars). Also, in Samba + we only search for ascii characters in 'c' and that + in all mb character sets with a compound character + containing c, if 'c' is not a match at position + p, then p[-1] > 0x7f. JRA. */ - push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); - p = strrchr_w(ws, UCS2_CHAR(c)); - if (!p) - return NULL; - *p = 0; - pull_ucs2_pstring(s2, ws); - return (char *)(s+strlen(s2)); + { + size_t len = strlen(s); + const char *cp = s; + BOOL got_mb = False; + + if (len == 0) + return NULL; + cp += (len - 1); + do { + if (c == *cp) { + /* Could be a match. Part of a multibyte ? */ + if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) { + /* Yep - go slow :-( */ + got_mb = True; + break; + } + /* No - we have a match ! */ + return cp; + } + } while (cp-- != s); + if (!got_mb) + return NULL; + } + + /* String contained a non-ascii char. Slow path. */ + { + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strrchr_w(ws, UCS2_CHAR(c)); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); + } } /*********************************************************************** @@ -1409,6 +1541,35 @@ void str_list_free(char ***list) SAFE_FREE(*list); } +/****************************************************************************** + version of standard_sub_basic() for string lists; uses alloc_sub_basic() + for the work + *****************************************************************************/ + +BOOL str_list_sub_basic( char **list, const char *smb_name ) +{ + char *s, *tmpstr; + + while ( *list ) { + s = *list; + tmpstr = alloc_sub_basic(smb_name, s); + if ( !tmpstr ) { + DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n")); + return False; + } + + *list = tmpstr; + + list++; + } + + return True; +} + +/****************************************************************************** + substritute a specific pattern in a string list + *****************************************************************************/ + BOOL str_list_substitute(char **list, const char *pattern, const char *insert) { char *p, *s, *t; @@ -1464,6 +1625,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) } } + list++; } diff --git a/source3/lib/version.c b/source3/lib/version.c new file mode 100644 index 0000000000..99f836c2d5 --- /dev/null +++ b/source3/lib/version.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + Samba Version functions + + Copyright (C) Stefan Metzmacher 2003 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +const char *samba_version_string(void) +{ +#ifndef SAMBA_VERSION_VENDOR_SUFFIX + return SAMBA_VERSION_OFFICIAL_STRING; +#else + static fstring samba_version; + static BOOL init_samba_version; + + if (init_samba_version) + return samba_version; + + snprintf(samba_version,sizeof(samba_version),"%s-%s", + SAMBA_VERSION_OFFICIAL_STRING, + SAMBA_VERSION_VENDOR_SUFFIX); + + init_samba_version = True; + return samba_version; +#endif +} -- cgit From 80a11b868d402174ad3afab37c8f461c3c6eeb1c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Sep 2003 03:49:43 +0000 Subject: Remove another dead file. (This used to be commit a5656a5756b3c1061d683d664a7f087182b39b47) --- source3/lib/ldap.c | 719 ----------------------------------------------------- 1 file changed, 719 deletions(-) delete mode 100644 source3/lib/ldap.c (limited to 'source3/lib') diff --git a/source3/lib/ldap.c b/source3/lib/ldap.c deleted file mode 100644 index 917e03a871..0000000000 --- a/source3/lib/ldap.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - Unix SMB/CIFS implementation. - LDAP protocol helper functions for SAMBA - Copyright (C) Jean François Micouleau 1998 - Copyright (C) Gerald Carter 2001 - Copyright (C) Shahms King 2001 - Copyright (C) Andrew Bartlett 2002 - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Jim McDonough 2003 - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -#ifdef HAVE_LDAP -/* TODO: -* persistent connections: if using NSS LDAP, many connections are made -* however, using only one within Samba would be nice -* -* Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK -* -* Other LDAP based login attributes: accountExpires, etc. -* (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT -* structures don't have fields for some of these attributes) -* -* SSL is done, but can't get the certificate based authentication to work -* against on my test platform (Linux 2.4, OpenLDAP 2.x) -*/ - -/* NOTE: this will NOT work against an Active Directory server -* due to the fact that the two password fields cannot be retrieved -* from a server; recommend using security = domain in this situation -* and/or winbind -*/ - -#include "smb_ldap.h" - -/* We need an internal mapping of LDAP * -> smb_ldap_privates so we implement - it in terms of a VK list. It's a little backwards but its quite efficent */ -static struct smb_ldap_privates *head; - -static struct smb_ldap_privates *get_internal(LDAP *ldap_struct) -{ - struct smb_ldap_privates *ret = head; - - while (NULL != ret && ret->ldap_struct != ldap_struct) { - ret = ret->next; - } - - return ret; -} - -#define SMB_LDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ - -/******************************************************************* - find the ldap password -******************************************************************/ -static BOOL smb_ldap_fetch_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("smb_ldap_fetch_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("smb_ldap_fetch_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); - - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} - -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -int smb_ldap_open_connection (struct smb_ldap_privates *ldap_state, - LDAP ** ldap_struct) -{ - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) - DEBUG(10, ("smb_ldap_open_connection: %s\n", ldap_state->uri)); - - if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } - -#else - - /* Parse the string manually */ - - { - int port = 0; - fstring protocol; - fstring host; - const char *p = ldap_state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; - } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); - } - } - - if ((*ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; - } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("smb_ldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) - { - if (version != LDAP_VERSION3) - { - version = LDAP_VERSION3; - if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } - } else { - ldap_v3 = True; - } - } - - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) - { - DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", - ldap_err2string(rc))); - return rc; - } - DEBUG (3, ("StartTLS issued: using a TLS connection\n")); - } else { - - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; - } -#else - DEBUG(0,("smb_ldap_open_connection: StartTLS not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - - DEBUG(2, ("smb_ldap_open_connection: connection opened\n")); - return rc; -} - - -/******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, - int *methodp, int freeit, void *arg) -{ - struct smb_ldap_privates *ldap_state = arg; - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - *whop = strdup(ldap_state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = strdup(ldap_state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; - } - return 0; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) - and actually does the connection. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -static int rebindproc_connect_with_state (LDAP *ldap_struct, - LDAP_CONST char *url, - ber_tag_t request, - ber_int_t msgid, void *arg) -{ - struct smb_ldap_privates *ldap_state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); - - return rc; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - Add a rebind function for authenticated referrals -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, - int *method, int freeit ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, get_internal(ldap_struct)); - -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - a rebind function for authenticated referrals - this also does the connection, but no void*. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, - ber_int_t msgid) -{ - return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, - get_internal(ld)); -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - connect to the ldap server under system privilege. -******************************************************************/ -int smb_ldap_connect_system(struct smb_ldap_privates *ldap_state, - LDAP * ldap_struct) -{ - int rc; - char *ldap_dn; - char *ldap_secret; - - if (NULL == get_internal(ldap_struct)) { - ldap_state->next = head; - } - - /* get the password */ - if (!smb_ldap_fetch_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } - - ldap_state->bind_dn = ldap_dn; - ldap_state->bind_secret = ldap_secret; - - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", - ldap_state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); -# endif -#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state); -# endif -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - - rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); - - if (rc != LDAP_SUCCESS) { - char *ld_error; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(0, - ("failed to bind to server with dn= %s Error: %s\n\t%s\n", - ldap_dn, ldap_err2string(rc), - ld_error)); - free(ld_error); - return rc; - } - - DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n")); - return rc; -} - -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -int smb_ldap_open(struct smb_ldap_privates *ldap_state) -{ - int rc; - SMB_ASSERT(ldap_state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, ("smb_ldap_open: cannot access LDAP when not root..\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - - if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMB_LDAP_DONT_PING_TIME) < time(NULL))) { - struct sockaddr_un addr; - socklen_t len; - int sd; - if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - ldap_state->last_ping = (time_t)0; - } else { - ldap_state->last_ping = time(NULL); - } - } - - if (ldap_state->ldap_struct != NULL) { - DEBUG(5,("smb_ldap_open: allready connected to the LDAP server\n")); - return LDAP_SUCCESS; - } - - if ((rc = smb_ldap_open_connection(ldap_state, &ldap_state->ldap_struct))) { - return rc; - } - - if ((rc = smb_ldap_connect_system(ldap_state, ldap_state->ldap_struct))) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - return rc; - } - - - ldap_state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} - -/********************************************************************** -Disconnect from LDAP server -*********************************************************************/ -NTSTATUS smb_ldap_close(struct smb_ldap_privates *ldap_state) -{ - if (!ldap_state) - return NT_STATUS_INVALID_PARAMETER; - - if (ldap_state->ldap_struct != NULL) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - } - - DEBUG(5,("The connection to the LDAP server was closed\n")); - /* maybe free the results here --metze */ - - return NT_STATUS_OK; -} - -static int smb_ldap_retry_open(struct smb_ldap_privates *ldap_state, int *attempts) -{ - int rc; - - SMB_ASSERT(ldap_state && attempts); - - if (*attempts != 0) { - /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */ - msleep((((*attempts)*(*attempts))/2)*1000); - } - (*attempts)++; - - if ((rc = smb_ldap_open(ldap_state))) { - DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts)); - return rc; - } - - return LDAP_SUCCESS; -} - - -int smb_ldap_search(struct smb_ldap_privates *ldap_state, - const char *base, int scope, const char *filter, - const char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - SMB_ASSERT(ldap_state); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_search_s(ldap_state->ldap_struct, base, scope, - filter, (char **)attrs, attrsonly, res); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_modify(struct smb_ldap_privates *ldap_state, char *dn, - LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_add(struct smb_ldap_privates *ldap_state, const char *dn, - LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_delete(struct smb_ldap_privates *ldap_state, char *dn) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_delete_s(ldap_state->ldap_struct, dn); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_extended_operation(struct smb_ldap_privates *ldap_state, - LDAP_CONST char *reqoid, - struct berval *reqdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, char **retoidp, - struct berval **retdatap) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -BOOL smb_ldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - - if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { - value = NULL; - DEBUG (10, ("smb_ldap_get_single_attribute: [%s] = []\n", attribute)); - - return False; - } - - pstrcpy(value, values[0]); - ldap_value_free(values); -#ifdef DEBUG_PASSWORDS - DEBUG (100, ("smb_ldap_get_single_attribute: [%s] = [%s]\n", attribute, value)); -#endif - return True; -} - - -/************************************************************************ -Routine to manage the LDAPMod structure array -manage memory used by the array, by each struct, and values - -************************************************************************/ -void smb_ldap_make_a_mod (LDAPMod *** modlist, int modop, - const char *attribute, const char *value) -{ - LDAPMod **mods; - int i; - int j; - - mods = *modlist; - - if (attribute == NULL || *attribute == '\0') - return; - - if (value == NULL || *value == '\0') - return; - - if (mods == NULL) - { - mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[0] = NULL; - } - - for (i = 0; mods[i] != NULL; ++i) { - if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) - break; - } - - if (mods[i] == NULL) - { - mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); - if (mods[i] == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[i]->mod_op = modop; - mods[i]->mod_values = NULL; - mods[i]->mod_type = strdup(attribute); - mods[i + 1] = NULL; - } - - if (value != NULL) - { - j = 0; - if (mods[i]->mod_values != NULL) { - for (; mods[i]->mod_values[j] != NULL; j++); - } - mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values, - (j + 2) * sizeof (char *)); - - if (mods[i]->mod_values == NULL) { - DEBUG (0, ("smb_ldap_make_a_mod: Memory allocation failure!\n")); - return; - } - mods[i]->mod_values[j] = strdup(value); - mods[i]->mod_values[j + 1] = NULL; - } - *modlist = mods; -} - -#endif -- cgit From a9cd4a6ae1709381f896605beb0c3e82c16b330e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:01:27 +0000 Subject: Merge from Samba 3.0: >For some reason testparm runs at debug level 2 which causes the module probe functions to >display verbose debugs. Increase the probe debugs to level 3. (This used to be commit be91bbd570bd94f67001aab9cfb2baf44b390097) --- source3/lib/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/module.c b/source3/lib/module.c index e2c6f6dcf5..941a6cfbe3 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -41,7 +41,7 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) handle = sys_dlopen(module_name, RTLD_LAZY); if(!handle) { - int level = is_probe ? 2 : 0; + int level = is_probe ? 3 : 0; DEBUG(level, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); -- cgit From d8231592bc4497fbec0a9ced20cd8cc84782bb9d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:02:12 +0000 Subject: Merge from Samba 3.0: >Fix for MacOS/X which uses STUPID BROKEN UNICODE COMPOSE CHARACTERS ! >(rant off :-). Inspired by work from Benjamin Riefenstahl . >Also add MacOSX/Darwin configure fixes. >Jerry - can we put this in 3.0 release ? :-). >Jeremy. (This used to be commit 67acde75d3569b612f87646ff0740f8020e8fdcf) --- source3/lib/charcnv.c | 79 +++++++++++++++++++++++++++++++++----------------- source3/lib/util_str.c | 14 +++++++-- 2 files changed, 65 insertions(+), 28 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 5f3cf64a68..dafc88fb77 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -176,6 +176,14 @@ static size_t convert_string_internal(charset_t from, charset_t to, descriptor = conv_handles[from][to]; + if (srclen == (size_t)-1) { + if (from == CH_UCS2) { + srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2; + } else { + srclen = strlen((const char *)src)+1; + } + } + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { if (!conv_silent) DEBUG(0,("convert_string_internal: Conversion not supported.\n")); @@ -248,31 +256,40 @@ size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen) { + /* + * NB. We deliberately don't do a strlen here is srclen == -1. + * This is very expensive over millions of calls and is taken + * care of in the slow path in convert_string_internal. JRA. + */ + if (srclen == 0) return 0; if (from != CH_UCS2 && to != CH_UCS2) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; size_t retval = 0; /* If all characters are ascii, fast path here. */ - while (srclen && destlen) { + while (slen && dlen) { if ((lastp = *p) <= 0x7f) { *q++ = *p++; - if (srclen != (size_t)-1) { - srclen--; + if (slen != (size_t)-1) { + slen--; } - destlen--; + dlen--; retval++; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen(p)+1; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; @@ -280,25 +297,28 @@ size_t convert_string(charset_t from, charset_t to, const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; /* If all characters are ascii, fast path here. */ - while ((srclen >= 2) && destlen) { - if ((lastp = *p) <= 0x7f && p[1] == 0) { + while ((slen >= 2) && dlen) { + if (((lastp = *p) <= 0x7f) && (p[1] == 0)) { *q++ = *p; - if (srclen != (size_t)-1) { - srclen -= 2; + if (slen != (size_t)-1) { + slen -= 2; } p += 2; - destlen--; + dlen--; retval++; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen_w((const void *)p)+2; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; @@ -306,29 +326,36 @@ size_t convert_string(charset_t from, charset_t to, const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; /* If all characters are ascii, fast path here. */ - while (srclen && (destlen >= 2)) { + while (slen && (dlen >= 2)) { if ((lastp = *p) <= 0x7F) { *q++ = *p++; *q++ = '\0'; - if (srclen != (size_t)-1) { - srclen--; + if (slen != (size_t)-1) { + slen--; } - destlen -= 2; + dlen -= 2; retval += 2; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen(p)+1; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; } + +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + general_case: +#endif return convert_string_internal(from, to, src, srclen, dest, destlen); } @@ -542,7 +569,7 @@ char *strdup_upper(const char *s) strupper_w(buffer); - size = convert_string(CH_UCS2, CH_UNIX, buffer, sizeof(buffer), out_buffer, sizeof(out_buffer)); + size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer)); if (size == -1) { return NULL; } diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 82b312e241..15ac1639a9 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -382,6 +382,10 @@ void string_replace(pstring s,char oldc,char newc) return; /* Slow (mb) path. */ +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + /* With compose characters we must restart from the beginning. JRA. */ + p = s; +#endif push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); @@ -1175,18 +1179,19 @@ char *string_truncate(char *s, unsigned int length) We convert via ucs2 for now. **/ -char *strchr_m(const char *s, char c) +char *strchr_m(const char *src, char c) { wpstring ws; pstring s2; smb_ucs2_t *p; + const char *s; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ - while (*s && (((unsigned char)s[0]) & 0x80)) { + for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) { if (*s == c) return s; } @@ -1194,6 +1199,11 @@ char *strchr_m(const char *s, char c) if (!*s) return NULL; +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + /* With compose characters we must restart from the beginning. JRA. */ + s = src; +#endif + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) -- cgit From aafb99dc8f14e061ca538c6f9822ba5b8253d40b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:19:07 +0000 Subject: Merge from Samba 3.0: >Still on my mb rampage. Ensure smbldap_make_mod() correctly detects old >values. >Jeremy. (This used to be commit 9df18a6c4ea30545297f9e5a0b10b440e6a0687e) --- source3/lib/smbldap.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 1ce03491da..781e6b976c 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -282,8 +282,9 @@ BOOL fetch_ldap_pw(char **dn, char** pw) } /******************************************************************* -search an attribute and return the first value found. + Search an attribute and return the first value found. ******************************************************************/ + BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, pstring value) { @@ -300,8 +301,7 @@ search an attribute and return the first value found. return False; } - if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) - { + if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) { DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", attribute, values[0])); ldap_value_free(values); @@ -402,32 +402,32 @@ search an attribute and return the first value found. *modlist = mods; } - /********************************************************************** Set attribute to newval in LDAP, regardless of what value the attribute had in LDAP before. *********************************************************************/ + void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, LDAPMod ***mods, const char *attribute, const char *newval) { - char **values = NULL; + pstring oldval; + BOOL existed; if (existing != NULL) { - values = ldap_get_values(ldap_struct, existing, attribute); + existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval); + } else { + existed = False; + *oldval = '\0'; } /* all of our string attributes are case insensitive */ - if ((values != NULL) && (values[0] != NULL) && - StrCaseCmp(values[0], newval) == 0) - { + if (existed && (StrCaseCmp(oldval, newval) == 0)) { /* Believe it or not, but LDAP will deny a delete and an add at the same time if the values are the same... */ - - ldap_value_free(values); return; } @@ -439,7 +439,7 @@ search an attribute and return the first value found. smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); } - if (values == NULL) { + if (!existed) { /* There has been no value before, so don't delete it. Here's a possible race: We might end up with duplicate attributes */ @@ -451,11 +451,9 @@ search an attribute and return the first value found. deny the complete operation if somebody changed the attribute behind our back. */ - smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); - ldap_value_free(values); + smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); } - /********************************************************************** Some varients of the LDAP rebind code do not pass in the third 'arg' pointer to a void*, so we try and work around it by assuming that the @@ -1329,3 +1327,23 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, return ret; } +/******************************************************************* + Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX. +********************************************************************/ + +char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry) +{ + char *utf8_dn, *unix_dn; + + utf8_dn = ldap_get_dn(ld, entry); + if (!utf8_dn) { + DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); + return NULL; + } + if (pull_utf8_allocate((void **) &unix_dn, utf8_dn) == (size_t)-1) { + DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 [%s]\n", utf8_dn)); + return NULL; + } + ldap_memfree(utf8_dn); + return unix_dn; +} -- cgit From bbc4f18f22b1ce5a247121a65e1bc1d00e585847 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 15 Sep 2003 12:59:09 +0000 Subject: Alias charset 646 internally (This used to be commit f4eb7acc7dfc400cc6524dccdd8081acd707f937) --- source3/lib/iconv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/lib') diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index c09bff5fd7..3d26d7e17c 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -57,6 +57,7 @@ static struct charset_functions builtin_functions[] = { {"UCS-2LE", iconv_copy, iconv_copy}, {"UTF8", utf8_pull, utf8_push}, {"ASCII", ascii_pull, ascii_push}, + {"646", ascii_pull, ascii_push}, {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, {NULL, NULL, NULL} }; -- cgit From 92347f2d0f3972db9e4e686db989d292689175be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 2003 23:36:58 +0000 Subject: Unregister event fix from metze. Jeremy. (This used to be commit b3b2b3d5e7c9d4995890bf7b156fc1176b042cfc) --- source3/lib/module.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/module.c b/source3/lib/module.c index 941a6cfbe3..38fcf0f329 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -210,18 +210,21 @@ void smb_run_idle_events(time_t now) struct smb_idle_list_ent *event = smb_idle_event_list; while (event) { + struct smb_idle_list_ent *next = event->next; time_t interval; - if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) { + if (event->interval <= 0) { + interval = SMB_IDLE_EVENT_DEFAULT_INTERVAL; + } else if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) { interval = event->interval; } else { interval = SMB_IDLE_EVENT_MIN_INTERVAL; } if (now >(event->lastrun+interval)) { - event->fn(&event->data,&event->interval,now); event->lastrun = now; + event->fn(&event->data,&event->interval,now); } - event = event->next; + event = next; } return; -- cgit From 8139c5fcfa6bd26ce03af41c374f84be48343666 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Sep 2003 21:57:46 +0000 Subject: Ensure that dup_sec_desc copies the 'type' field correctly. This caused me to expose a type arguement to make_sec_desc(). We weren't copying the SE_DESC_DACL_AUTO_INHERITED flag which could cause errors on auto inherited checks. Jeremy. (This used to be commit 546b2271c08735ac1049a453abac996d794aa364) --- source3/lib/util_seaccess.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index eba8cab7fb..2482d582d2 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -435,7 +435,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, correct. Perhaps the user and group should be passed in as parameters by the caller? */ - sd = make_sec_desc(ctx, SEC_DESC_REVISION, + sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, parent_ctr->owner_sid, parent_ctr->grp_sid, parent_ctr->sacl, @@ -479,7 +479,7 @@ NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) return NT_STATUS_NO_MEMORY; - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; -- cgit From 492072314b12f09b85353be971a0ab7d1329b179 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 22 Sep 2003 17:54:34 +0000 Subject: fix some warnings found by the Sun C compiler (This used to be commit 585764305aa84a7732f71f2e01227e1a6a08664f) --- source3/lib/util_unistr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index fd51f3c57d..e7c200218e 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -841,5 +841,5 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) strncpy_w(dst->buffer, src, dst->uni_max_len); return dst; -}; +} -- cgit From 602ad283b4724acac0a416cd1fd1124ce89ee316 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 24 Sep 2003 15:16:57 +0000 Subject: * sync more files from 3.0 * set version string to "CVS 3.1.0alpha1" (This used to be commit c6a61ffcbd0c95afd94bd33fd832b24bc8209de5) --- source3/lib/afs.c | 60 ++++++++++++++++++++++++++++++-------------------- source3/lib/util_sec.c | 4 ++++ 2 files changed, 40 insertions(+), 24 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/afs.c b/source3/lib/afs.c index b96703e986..882442a79f 100644 --- a/source3/lib/afs.c +++ b/source3/lib/afs.c @@ -35,18 +35,6 @@ _syscall5(int, afs_syscall, int, subcall, char *, cmarg, int, follow); -char *afs_cell(void) -{ - static char *cell = NULL; - - if (cell == NULL) { - cell = strdup(lp_realm()); - strlower_m(cell); - } - - return cell; -} - struct ClearToken { uint32 AuthHandle; char HandShakeKey[8]; @@ -65,7 +53,8 @@ struct ClearToken { to avoid. */ -static BOOL afs_settoken(char *username, const struct ClearToken *ctok, +static BOOL afs_settoken(const char *username, const char *cell, + const struct ClearToken *ctok, char *v4tkt_data, int v4tkt_length) { int ret; @@ -94,13 +83,13 @@ static BOOL afs_settoken(char *username, const struct ClearToken *ctok, memcpy(p, &tmp, sizeof(uint32)); p += sizeof(uint32); - tmp = strlen(afs_cell()); + tmp = strlen(cell); if (tmp >= MAXKTCREALMLEN) { DEBUG(1, ("Realm too long\n")); return False; } - strncpy(p, afs_cell(), tmp); + strncpy(p, cell, tmp); p += tmp; *p = 0; p +=1; @@ -135,12 +124,14 @@ static BOOL afs_settoken(char *username, const struct ClearToken *ctok, For the comments "Alice" is the User to be auth'ed, and "Bob" is the AFS server. */ -BOOL afs_login(char *username) +BOOL afs_login(connection_struct *conn) { fstring ticket; char *p = ticket; uint32 len; struct afs_key key; + pstring afs_username; + char *cell; struct ClearToken ct; @@ -148,13 +139,28 @@ BOOL afs_login(char *username) des_key_schedule key_schedule; - DEBUG(10, ("Trying to log into AFS for user %s@%s\n", - username, afs_cell())); + pstrcpy(afs_username, lp_afs_username_map()); + standard_sub_conn(conn, afs_username, sizeof(afs_username)); + + cell = strchr(afs_username, '@'); + + if (cell == NULL) { + DEBUG(1, ("AFS username doesn't contain a @, " + "could not find cell\n")); + return False; + } + + *cell = '\0'; + cell += 1; + strlower_m(cell); + + DEBUG(10, ("Trying to log into AFS for user %s@%s\n", + afs_username, cell)); if (!secrets_init()) return False; - if (!secrets_fetch_afs_key(afs_cell(), &key)) { + if (!secrets_fetch_afs_key(cell, &key)) { DEBUG(5, ("Could not fetch AFS service key\n")); return False; } @@ -172,14 +178,20 @@ BOOL afs_login(char *username) p += 1; /* "Alice", the client username */ - strncpy(p, username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); + strncpy(p, afs_username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; - strncpy(p, afs_cell(), sizeof(ticket)-PTR_DIFF(p,ticket)-1); + strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; - ct.ViceId = getuid(); + /* As long as we still only use the effective UID we need to set the + * token for it here as well. This involves patching AFS in two + * places. Once we start using the real uid where we have the + * setresuid function, we can use getuid() here which would be more + * correct. */ + + ct.ViceId = geteuid(); DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); /* Alice's network layer address. At least Openafs-1.2.10 @@ -235,12 +247,12 @@ BOOL afs_login(char *username) ZERO_STRUCT(key); - return afs_settoken(username, &ct, ticket, len); + return afs_settoken(afs_username, cell, &ct, ticket, len); } #else -BOOL afs_login(char *username) +BOOL afs_login(connection_struct *conn) { return True; } diff --git a/source3/lib/util_sec.c b/source3/lib/util_sec.c index 132748ce13..1980b8bfb7 100644 --- a/source3/lib/util_sec.c +++ b/source3/lib/util_sec.c @@ -183,6 +183,10 @@ void gain_root_group_privilege(void) void set_effective_uid(uid_t uid) { #if USE_SETRESUID + /* On Systems which have this function, would it not be more + * appropriate to also set the real uid by doing + * setresuid(uid,uid,-1)? This would make patching AFS + * unnecessary. See comment in lib/afs.c. */ setresuid(-1,uid,-1); #endif -- cgit From 5400952f7f74d6e656fcf4ded173868ecec3cb77 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:17:09 +0000 Subject: Merge from 3.0: >Fix for #480. Change the interface for init_unistr2 to not take a length >but a flags field. We were assuming that 2*strlen(mb_string) == length of ucs2-le string. >This is not the case. Count it after conversion. >Jeremy. (This used to be commit e2ab9e54cd0ec0002175cf18ff364f4aebaf85a0) --- source3/lib/util_unistr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index e7c200218e..e90a824395 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -819,22 +819,25 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) { size_t len; - if (!src) return NULL; + if (!src) + return NULL; len = strlen_w(src); /* allocate UNISTR2 destination if not given */ if (!dst) { dst = (UNISTR2*) talloc(ctx, sizeof(UNISTR2)); - if (!dst) return NULL; + if (!dst) + return NULL; } if (!dst->buffer) { dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1)); - if (!dst->buffer) return NULL; + if (!dst->buffer) + return NULL; } /* set UNISTR2 parameters */ dst->uni_max_len = len + 1; - dst->undoc = 0; + dst->offset = 0; dst->uni_str_len = len; /* copy the actual unicode string */ @@ -842,4 +845,3 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) return dst; } - -- cgit From 10ab4ce58abbd9b38bfb43165452cf45005159b4 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:23:56 +0000 Subject: Merge from 3.0: >iconv isn't const safe. Neither should smb_iconv be. >Jeremy. (This used to be commit 7bd450f8b678e835ba4f9cfdc3d096b04da6f8f7) --- source3/lib/iconv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 3d26d7e17c..0326ca7061 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -136,7 +136,7 @@ static size_t sys_iconv(void *cd, * enough that Samba works on systems that don't have iconv. **/ size_t smb_iconv(smb_iconv_t cd, - const char **inbuf, size_t *inbytesleft, + char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { char cvtbuf[2048]; -- cgit From e1f16f33219b44f0a66af0da0a02d8e8781a24f6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 1 Oct 2003 17:02:09 +0000 Subject: merge of parameter changes from 3.0 and fix for bug 550 (This used to be commit b6433f5db77a1d62309946c6f23c18c6c299d0c5) --- source3/lib/system.c | 8 +++++--- source3/lib/system_smbd.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/system.c b/source3/lib/system.c index b020a20373..2e95efec79 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -693,7 +693,6 @@ int sys_getgroups(int setlen, gid_t *gidset) #endif /* HAVE_BROKEN_GETGROUPS */ } -#ifdef HAVE_SETGROUPS /************************************************************************** Wrapper for setgroups. Deals with broken (int) case. Automatically used @@ -702,6 +701,11 @@ int sys_getgroups(int setlen, gid_t *gidset) int sys_setgroups(int setlen, gid_t *gidset) { +#if !defined(HAVE_SETGROUPS) + errno = ENOSYS; + return -1; +#endif /* HAVE_SETGROUPS */ + #if !defined(HAVE_BROKEN_GETGROUPS) return setgroups(setlen, gidset); #else @@ -742,8 +746,6 @@ int sys_setgroups(int setlen, gid_t *gidset) #endif /* HAVE_BROKEN_GETGROUPS */ } -#endif /* HAVE_SETGROUPS */ - /************************************************************************** Wrappers for setpwent(), getpwent() and endpwent() ****************************************************************************/ diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index bcbc8c61e6..73c910e631 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -92,7 +92,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in restore_re_gid(); - if (setgroups(ngrp_saved, gids_saved) != 0) { + if (sys_setgroups(ngrp_saved, gids_saved) != 0) { /* yikes! */ DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); smb_panic("getgrouplist: failed to reset group list!\n"); -- cgit From 73953efac3e219e67d127e31e965756d8fa46104 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 2003 19:33:27 +0000 Subject: Allow ^C to interrupt smbpasswd if using our getpass. Jeremy. (This used to be commit 8a284463458cfaaff9986bbc459dfc113f921c6c) --- source3/lib/getsmbpass.c | 148 +++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 62 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/getsmbpass.c b/source3/lib/getsmbpass.c index b6ae09b318..93449b004d 100644 --- a/source3/lib/getsmbpass.c +++ b/source3/lib/getsmbpass.c @@ -83,71 +83,95 @@ static int tcsetattr(int fd, int flags, struct sgttyb *t) static struct termios t; #endif /* SYSV_TERMIO */ +static SIG_ATOMIC_T gotintr; +static int in_fd = -1; + +/*************************************************************** + Signal function to tell us were ^C'ed. +****************************************************************/ + +static void gotintr_sig(void) +{ + gotintr = 1; + if (in_fd != -1) + close(in_fd); /* Safe way to force a return. */ + in_fd = -1; +} + char *getsmbpass(const char *prompt) { - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) - { - if (ECHO_IS_ON(t)) - { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST gotintr_sig); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) { + in = stdin; + out = stderr; + } else { + out = in; + } + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) { + if (ECHO_IS_ON(t)) { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } else { + echo_off = 0; + } + } else { + echo_off = 0; + } + + /* Write the prompt. */ + fputs(prompt, out); + fflush(out); + + /* Read the password. */ + buf[0] = 0; + if (!gotintr) { + in_fd = fileno(in); + fgets(buf, bufsize, in); + } + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) { + if (gotintr && in_fd == -1) + in = fopen ("/dev/tty", "w+"); + if (in != NULL) + tcsetattr (fileno (in), TCSANOW, &t); + } + + if (in != stdin) /* We opened the terminal; now close it. */ + fclose(in); + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + + if (gotintr_sig) { + printf("Interupted by signal.\n"); + fflush(stdout); + exit(1); } - else - echo_off = 0; - } - else - echo_off = 0; - - /* Write the prompt. */ - fputs (prompt, out); - fflush (out); - - /* Read the password. */ - buf[0] = 0; - fgets(buf, bufsize, in); - nread = strlen(buf); - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - - /* Restore echoing. */ - if (echo_off) - (void) tcsetattr (fileno (in), TCSANOW, &t); - - if (in != stdin) - /* We opened the terminal; now close it. */ - fclose (in); - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - - printf("\n"); - return buf; + return buf; } #else -- cgit From b8092fbf99d01783110566b51dfaf26d4802f403 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 2003 21:17:46 +0000 Subject: Fixed silly typo checking for signal_handler not signal. Jeremy. (This used to be commit 202d4e46527993d359df7cd04fb611c22cc920c3) --- source3/lib/getsmbpass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/getsmbpass.c b/source3/lib/getsmbpass.c index 93449b004d..27cd5e6dfa 100644 --- a/source3/lib/getsmbpass.c +++ b/source3/lib/getsmbpass.c @@ -166,7 +166,7 @@ char *getsmbpass(const char *prompt) printf("\n"); - if (gotintr_sig) { + if (gotintr) { printf("Interupted by signal.\n"); fflush(stdout); exit(1); -- cgit From 762e7e1dff89cc14b0130fc9a22038b0845630a2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Oct 2003 01:24:48 +0000 Subject: split some security related functions in their own files. (no need to include all of smbd files to use some basic sec functions) also minor compile fixes (This used to be commit 66074d3b097d8cf2a231bf08c7f4db62da68189d) --- source3/lib/privileges.c | 345 +++++++++++++++++++++++++++++ source3/lib/secace.c | 285 ++++++++++++++++++++++++ source3/lib/secacl.c | 118 ++++++++++ source3/lib/secdesc.c | 522 ++++++++++++++++++++++++++++++++++++++++++++ source3/lib/talloc.c | 21 -- source3/lib/util_seaccess.c | 129 ----------- source3/lib/util_sid.c | 2 +- 7 files changed, 1271 insertions(+), 151 deletions(-) create mode 100644 source3/lib/privileges.c create mode 100644 source3/lib/secace.c create mode 100644 source3/lib/secacl.c create mode 100644 source3/lib/secdesc.c (limited to 'source3/lib') diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c new file mode 100644 index 0000000000..1c23d9e40e --- /dev/null +++ b/source3/lib/privileges.c @@ -0,0 +1,345 @@ +/* + Unix SMB/CIFS implementation. + Privileges handling functions + Copyright (C) Jean François Micouleau 1998-2001 + Copyright (C) Simo Sorce 2002-2003 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* defines */ + +#define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) +#define NTSTATUS_CHECK(err, label, str1, str2) do { if (!NT_STATUS_IS_OK(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0) + +/**************************************************************************** + Check if a user is a mapped group. + + This function will check if the group SID is mapped onto a + system managed gid or onto a winbind manged sid. + In the first case it will be threated like a mapped group + and the backend should take the member list with a getgrgid + and ignore any user that have been possibly set into the group + object. + + In the second case, the group is a fully SAM managed group + served back to the system through winbind. In this case the + members of a Local group are "unrolled" to cope with the fact + that unix cannot contain groups inside groups. + The backend MUST never call any getgr* / getpw* function or + loops with winbind may happen. + ****************************************************************************/ + +#if 0 +NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid) +{ + NTSTATUS result; + gid_t id; + + /* look if mapping exist, do not make idmap alloc an uid if SID is not found */ + result = idmap_get_gid_from_sid(&id, sid, False); + if (NT_STATUS_IS_OK(result)) { + *mapped = gid_is_in_winbind_range(id); + } else { + *mapped = False; + } + + return result; +} +#endif + +/**************************************************************************** + duplicate alloc luid_attr + ****************************************************************************/ +NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la) +{ + NTSTATUS ret; + + *new_la = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR)); + ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr"); + + (*new_la)->luid.high = old_la->luid.high; + (*new_la)->luid.low = old_la->luid.low; + (*new_la)->attr = old_la->attr; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + initialise a privilege list + ****************************************************************************/ +NTSTATUS init_privilege(PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + TALLOC_CTX *mem_ctx = talloc_init("privilege set"); + ALLOC_CHECK(mem_ctx, ret, done, "init_privilege"); + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + (*priv_set)->ext_ctx = True; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +void reset_privilege(PRIVILEGE_SET *priv_set) +{ + priv_set->count = 0; + priv_set->control = 0; + priv_set->set = NULL; +} + +void destroy_privilege(PRIVILEGE_SET **priv_set) +{ + reset_privilege(*priv_set); + if (!((*priv_set)->ext_ctx)) + /* mem_ctx is local, destroy it */ + talloc_destroy((*priv_set)->mem_ctx); + *priv_set = NULL; +} + +/**************************************************************************** + add a privilege to a privilege array + ****************************************************************************/ +NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + + /* check if the privilege is not already in the list */ + if (NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* we can allocate memory to add the new privilege */ + + new_set = (LUID_ATTR *)talloc_realloc(priv_set->mem_ctx, priv_set->set, (priv_set->count + 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "add_privilege"); + + new_set[priv_set->count].luid.high = set.luid.high; + new_set[priv_set->count].luid.low = set.luid.low; + new_set[priv_set->count].attr = set.attr; + + priv_set->count++; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + add all the privileges to a privilege array + ****************************************************************************/ +NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set) +{ + NTSTATUS result = NT_STATUS_OK; + LUID_ATTR set; + + set.attr = 0; + set.luid.high = 0; + + /* TODO: set a proper list of privileges */ + set.luid.low = SE_PRIV_ADD_USERS; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_ADD_MACHINES; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_PRINT_OPERATOR; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + +done: + return result; +} + +/**************************************************************************** + check if the privilege list is empty + ****************************************************************************/ +NTSTATUS check_empty_privilege(PRIVILEGE_SET *priv_set) +{ + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + if (priv_set->count == 0) + return NT_STATUS_OK; + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + check if the privilege is in the privilege list + ****************************************************************************/ +NTSTATUS check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + int i; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* if the list is empty, obviously we can't have it */ + if (NT_STATUS_IS_OK(check_empty_privilege(priv_set))) + return NT_STATUS_UNSUCCESSFUL; + + for (i = 0; i < priv_set->count; i++) { + LUID_ATTR *cur_set; + + cur_set = &priv_set->set[i]; + /* check only the low and high part. Checking the attr field has no meaning */ + if ( (cur_set->luid.low == set.luid.low) && + (cur_set->luid.high == set.luid.high) ) { + return NT_STATUS_OK; + } + } + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + remove a privilege from a privilege array + ****************************************************************************/ +NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i,j; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* check if the privilege is in the list */ + if (!NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* special case if it's the only privilege in the list */ + if (priv_set->count == 1) { + reset_privilege(priv_set); + return NT_STATUS_OK; + } + + /* + * the privilege is there, create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "remove_privilege"); + + for (i=0, j=0; i < priv_set->count; i++) { + if ( (old_set[i].luid.low == set.luid.low) && + (old_set[i].luid.high == set.luid.high) ) { + continue; + } + + new_set[j].luid.low = old_set[i].luid.low; + new_set[j].luid.high = old_set[i].luid.high; + new_set[j].attr = old_set[i].attr; + + j++; + } + + if (j != priv_set->count - 1) { + DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); + DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); + return NT_STATUS_INTERNAL_ERROR; + } + + /* ok everything is fine */ + + priv_set->count--; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + duplicates a privilege array + the new privilege set must be passed inited + (use init_privilege or init_priv_with_ctx) + ****************************************************************************/ +NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i; + + if (!new_priv_set || !priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* special case if there are no privileges in the list */ + if (priv_set->count == 0) { + return NT_STATUS_OK; + } + + /* + * create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "dup_priv_set"); + + for (i=0; i < priv_set->count; i++) { + + new_set[i].luid.low = old_set[i].luid.low; + new_set[i].luid.high = old_set[i].luid.high; + new_set[i].attr = old_set[i].attr; + } + + new_priv_set->count = priv_set->count; + new_priv_set->control = priv_set->control; + new_priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} diff --git a/source3/lib/secace.c b/source3/lib/secace.c new file mode 100644 index 0000000000..6769f1288a --- /dev/null +++ b/source3/lib/secace.c @@ -0,0 +1,285 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACE handling functions + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Check if ACE has OBJECT type. +********************************************************************/ + +BOOL sec_ace_object(uint8 type) +{ + if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { + return True; + } + return False; +} + +/******************************************************************* + copy a SEC_ACE structure. +********************************************************************/ +void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) +{ + ace_dest->type = ace_src->type; + ace_dest->flags = ace_src->flags; + ace_dest->size = ace_src->size; + ace_dest->info.mask = ace_src->info.mask; + ace_dest->obj_flags = ace_src->obj_flags; + memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE); + memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE); + sid_copy(&ace_dest->trustee, &ace_src->trustee); +} + +/******************************************************************* + Sets up a SEC_ACE structure. +********************************************************************/ + +void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) +{ + t->type = type; + t->flags = flag; + t->size = sid_size(sid) + 8; + t->info = mask; + + ZERO_STRUCTP(&t->trustee); + sid_copy(&t->trustee, sid); +} + +/******************************************************************* + adds new SID with its permissions to ACE list +********************************************************************/ + +NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + *num += 1; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num - 1; i ++) + sec_ace_copy(&(*new)[i], &old[i]); + + (*new)[i].type = 0; + (*new)[i].flags = 0; + (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); + (*new)[i].info.mask = mask; + sid_copy(&(*new)[i].trustee, sid); + return NT_STATUS_OK; +} + +/******************************************************************* + modify SID's permissions at ACL +********************************************************************/ + +NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER; + + for (i = 0; i < num; i ++) { + if (sid_compare(&ace[i].trustee, sid) == 0) { + ace[i].info.mask = mask; + return NT_STATUS_OK; + } + } + return NT_STATUS_NOT_FOUND; +} + +/******************************************************************* + delete SID from ACL +********************************************************************/ + +NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid) +{ + unsigned int i = 0; + unsigned int n_del = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num; i ++) { + if (sid_compare(&old[i].trustee, sid) != 0) + sec_ace_copy(&(*new)[i], &old[i]); + else + n_del ++; + } + if (n_del == 0) + return NT_STATUS_NOT_FOUND; + else { + *num -= n_del; + return NT_STATUS_OK; + } +} + +/******************************************************************* + Compares two SEC_ACE structures +********************************************************************/ + +BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) return True; + + /* Check top level stuff */ + + if (s1->type != s2->type || s1->flags != s2->flags || + s1->info.mask != s2->info.mask) { + return False; + } + + /* Check SID */ + + if (!sid_equal(&s1->trustee, &s2->trustee)) { + return False; + } + + return True; +} + +int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; + int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; + + if (a1_inh == a2_inh) + return 0; + + if (!a1_inh && a2_inh) + return -1; + return 1; +} + +/******************************************************************* + Comparison function to apply the order explained below in a group. +*******************************************************************/ + +int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return -1; + + if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return 1; + + /* Both access denied or access allowed. */ + + /* 1. ACEs that apply to the object itself */ + + if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return -1; + else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return 1; + + /* 2. ACEs that apply to a subobject of the object, such as + * a property set or property. */ + + if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return -1; + else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return 1; + + return 0; +} + +/******************************************************************* + Functions to convert a SEC_DESC ACE DACL list into canonical order. + JRA. + +--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp + +The following describes the preferred order: + + To ensure that noninherited ACEs have precedence over inherited ACEs, + place all noninherited ACEs in a group before any inherited ACEs. + This ordering ensures, for example, that a noninherited access-denied ACE + is enforced regardless of any inherited ACE that allows access. + + Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: + 1. Access-denied ACEs that apply to the object itself + 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property + 3. Access-allowed ACEs that apply to the object itself + 4. Access-allowed ACEs that apply to a subobject of the object" + +********************************************************************/ + +void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces) +{ + unsigned int i; + + if (!srclist || num_aces == 0) + return; + + /* Sort so that non-inherited ACE's come first. */ + qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp); + + /* Find the boundary between non-inherited ACEs. */ + for (i = 0; i < num_aces; i++ ) { + SEC_ACE *curr_ace = &srclist[i]; + + if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) + break; + } + + /* i now points at entry number of the first inherited ACE. */ + + /* Sort the non-inherited ACEs. */ + if (i) + qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); + + /* Now sort the inherited ACEs. */ + if (num_aces - i) + qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); +} + +/******************************************************************* + Check if this ACE has a SID in common with the token. +********************************************************************/ + +BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) +{ + size_t i; + + for (i = 0; i < token->num_sids; i++) { + if (sid_equal(&ace->trustee, &token->user_sids[i])) + return True; + } + + return False; +} diff --git a/source3/lib/secacl.c b/source3/lib/secacl.c new file mode 100644 index 0000000000..756685a821 --- /dev/null +++ b/source3/lib/secacl.c @@ -0,0 +1,118 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACL handling routines + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Create a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) +{ + SEC_ACL *dst; + int i; + + if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) + return NULL; + + dst->revision = revision; + dst->num_aces = num_aces; + dst->size = SEC_ACL_HEADER_SIZE; + + /* Now we need to return a non-NULL address for the ace list even + if the number of aces required is zero. This is because there + is a distinct difference between a NULL ace and an ace with zero + entries in it. This is achieved by checking that num_aces is a + positive number. */ + + if ((num_aces) && + ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) + == NULL)) { + return NULL; + } + + for (i = 0; i < num_aces; i++) { + dst->ace[i] = ace_list[i]; /* Structure copy. */ + dst->size += ace_list[i].size; + } + + return dst; +} + +/******************************************************************* + Duplicate a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) +{ + if(src == NULL) + return NULL; + + return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); +} + +/******************************************************************* + Compares two SEC_ACL structures +********************************************************************/ + +BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) +{ + unsigned int i, j; + + /* Trivial cases */ + + if (!s1 && !s2) return True; + if (!s1 || !s2) return False; + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->num_aces != s2->num_aces) { + DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + /* The ACEs could be in any order so check each ACE in s1 against + each ACE in s2. */ + + for (i = 0; i < s1->num_aces; i++) { + BOOL found = False; + + for (j = 0; j < s2->num_aces; j++) { + if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { + found = True; + break; + } + } + + if (!found) return False; + } + + return True; +} diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c new file mode 100644 index 0000000000..411185dbfa --- /dev/null +++ b/source3/lib/secdesc.c @@ -0,0 +1,522 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_DESC handling functions + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Works out the linearization size of a SEC_DESC. +********************************************************************/ + +size_t sec_desc_size(SEC_DESC *psd) +{ + size_t offset; + + if (!psd) return 0; + + offset = SEC_DESC_HEADER_SIZE; + + /* don't align */ + + if (psd->owner_sid != NULL) + offset += sid_size(psd->owner_sid); + + if (psd->grp_sid != NULL) + offset += sid_size(psd->grp_sid); + + if (psd->sacl != NULL) + offset += psd->sacl->size; + + if (psd->dacl != NULL) + offset += psd->dacl->size; + + return offset; +} + +/******************************************************************* + Compares two SEC_DESC structures +********************************************************************/ + +BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) { + goto done; + } + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->type!= s2->type) { + DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", + s1->type, s2->type)); + return False; + } + + /* Check owner and group */ + + if (!sid_equal(s1->owner_sid, s2->owner_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->owner_sid); + sid_to_string(str2, s2->owner_sid); + + DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", + str1, str2)); + return False; + } + + if (!sid_equal(s1->grp_sid, s2->grp_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->grp_sid); + sid_to_string(str2, s2->grp_sid); + + DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", + str1, str2)); + return False; + } + + /* Check ACLs present in one but not the other */ + + if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || + (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); + return False; + } + + /* Sigh - we have to do it the hard way by iterating over all + the ACEs in the ACLs */ + + if (!sec_acl_equal(s1->dacl, s2->dacl) || + !sec_acl_equal(s1->sacl, s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); + return False; + } + + done: + DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); + return True; +} + +/******************************************************************* + Merge part of security descriptor old_sec in to the empty sections of + security descriptor new_sec. +********************************************************************/ + +SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb) +{ + DOM_SID *owner_sid, *group_sid; + SEC_DESC_BUF *return_sdb; + SEC_ACL *dacl, *sacl; + SEC_DESC *psd = NULL; + uint16 secdesc_type; + size_t secdesc_size; + + /* Copy over owner and group sids. There seems to be no flag for + this so just check the pointer values. */ + + owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : + old_sdb->sec->owner_sid; + + group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : + old_sdb->sec->grp_sid; + + secdesc_type = new_sdb->sec->type; + + /* Ignore changes to the system ACL. This has the effect of making + changes through the security tab audit button not sticking. + Perhaps in future Samba could implement these settings somehow. */ + + sacl = NULL; + secdesc_type &= ~SEC_DESC_SACL_PRESENT; + + /* Copy across discretionary ACL */ + + if (secdesc_type & SEC_DESC_DACL_PRESENT) { + dacl = new_sdb->sec->dacl; + } else { + dacl = old_sdb->sec->dacl; + } + + /* Create new security descriptor from bits */ + + psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, + owner_sid, group_sid, sacl, dacl, &secdesc_size); + + return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); + + return(return_sdb); +} + +/******************************************************************* + Creates a SEC_DESC structure +********************************************************************/ + +SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, + DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) +{ + SEC_DESC *dst; + uint32 offset = 0; + + *sd_size = 0; + + if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) + return NULL; + + dst->revision = revision; + dst->type = type; + + if (sacl) + dst->type |= SEC_DESC_SACL_PRESENT; + if (dacl) + dst->type |= SEC_DESC_DACL_PRESENT; + + dst->off_owner_sid = 0; + dst->off_grp_sid = 0; + dst->off_sacl = 0; + dst->off_dacl = 0; + + if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) + goto error_exit; + + if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) + goto error_exit; + + if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) + goto error_exit; + + if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) + goto error_exit; + + offset = SEC_DESC_HEADER_SIZE; + + /* + * Work out the linearization sizes. + */ + + if (dst->sacl != NULL) { + dst->off_sacl = offset; + offset += dst->sacl->size; + } + if (dst->dacl != NULL) { + dst->off_dacl = offset; + offset += dst->dacl->size; + } + + if (dst->owner_sid != NULL) { + dst->off_owner_sid = offset; + offset += sid_size(dst->owner_sid); + } + + if (dst->grp_sid != NULL) { + dst->off_grp_sid = offset; + offset += sid_size(dst->grp_sid); + } + + *sd_size = (size_t)offset; + return dst; + +error_exit: + + *sd_size = 0; + return NULL; +} + +/******************************************************************* + Duplicate a SEC_DESC structure. +********************************************************************/ + +SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) +{ + size_t dummy; + + if(src == NULL) + return NULL; + + return make_sec_desc( ctx, src->revision, src->type, + src->owner_sid, src->grp_sid, src->sacl, + src->dacl, &dummy); +} + +/******************************************************************* + Creates a SEC_DESC structure with typical defaults. +********************************************************************/ + +SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *dacl, size_t *sd_size) +{ + return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + owner_sid, grp_sid, NULL, dacl, sd_size); +} + +/******************************************************************* + Creates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc) +{ + SEC_DESC_BUF *dst; + + if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL) + return NULL; + + /* max buffer size (allocated size) */ + dst->max_len = (uint32)len; + dst->len = (uint32)len; + + if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) { + return NULL; + } + + dst->ptr = 0x1; + + return dst; +} + +/******************************************************************* + Duplicates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src) +{ + if(src == NULL) + return NULL; + + return make_sec_desc_buf( ctx, src->len, src->sec); +} + +/******************************************************************* + Add a new SID with its permissions to SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/******************************************************************* + Modify a SID's permissions in a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) +{ + NTSTATUS status; + + if (!sd || !sid) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + return NT_STATUS_OK; +} + +/******************************************************************* + Delete a SID from a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd[0] || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/* Create a child security descriptor using another security descriptor as + the parent container. This child object can either be a container or + non-container object. */ + +SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, + BOOL child_container) +{ + SEC_DESC_BUF *sdb; + SEC_DESC *sd; + SEC_ACL *new_dacl, *the_acl; + SEC_ACE *new_ace_list = NULL; + unsigned int new_ace_list_ndx = 0, i; + size_t size; + + /* Currently we only process the dacl when creating the child. The + sacl should also be processed but this is left out as sacls are + not implemented in Samba at the moment.*/ + + the_acl = parent_ctr->dacl; + + if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) + return NULL; + + for (i = 0; the_acl && i < the_acl->num_aces; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; + uint8 new_flags = 0; + BOOL inherit = False; + fstring sid_str; + + /* The OBJECT_INHERIT_ACE flag causes the ACE to be + inherited by non-container children objects. Container + children objects will inherit it as an INHERIT_ONLY + ACE. */ + + if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { + + if (!child_container) { + new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; + } else { + new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } + + inherit = True; + } + + /* The CONAINER_INHERIT_ACE flag means all child container + objects will inherit and use the ACE. */ + + if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { + if (!child_container) { + inherit = False; + } else { + new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; + } + } + + /* The INHERIT_ONLY_ACE is not used by the se_access_check() + function for the parent container, but is inherited by + all child objects as a normal ACE. */ + + if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + /* Move along, nothing to see here */ + } + + /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE + is inherited by child objects but not grandchildren + objects. We clear the object inherit and container + inherit flags in the inherited ACE. */ + + if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + /* Add ACE to ACE list */ + + if (!inherit) + continue; + + init_sec_access(&new_ace->info, ace->info.mask); + init_sec_ace(new_ace, &ace->trustee, ace->type, + new_ace->info, new_flags); + + sid_to_string(sid_str, &ace->trustee); + + DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " + " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, + ace->type, ace->flags, ace->info.mask, + sid_str, new_ace->type, new_ace->flags, + new_ace->info.mask)); + + new_ace_list_ndx++; + } + + /* Create child security descriptor to return */ + + new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); + + /* Use the existing user and group sids. I don't think this is + correct. Perhaps the user and group should be passed in as + parameters by the caller? */ + + sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + parent_ctr->owner_sid, + parent_ctr->grp_sid, + parent_ctr->sacl, + new_dacl, &size); + + sdb = make_sec_desc_buf(ctx, size, sd); + + return sdb; +} + +/******************************************************************* + Sets up a SEC_ACCESS structure. +********************************************************************/ + +void init_sec_access(SEC_ACCESS *t, uint32 mask) +{ + t->mask = mask; +} + diff --git a/source3/lib/talloc.c b/source3/lib/talloc.c index b6c8b2efdf..485dc28f31 100644 --- a/source3/lib/talloc.c +++ b/source3/lib/talloc.c @@ -54,27 +54,6 @@ #include "includes.h" -struct talloc_chunk { - struct talloc_chunk *next; - size_t size; - void *ptr; -}; - - -struct talloc_ctx { - struct talloc_chunk *list; - size_t total_alloc_size; - - /** The name recorded for this pool, if any. Should describe - * the purpose for which it was allocated. The string is - * allocated within the pool. **/ - char *name; - - /** Pointer to the next allocate talloc pool, so that we can - * summarize all talloc memory usage. **/ - struct talloc_ctx *next_ctx; -}; - /** * Start of linked list of all talloc pools. diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index 2482d582d2..cb0f46e2f9 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -23,22 +23,6 @@ extern DOM_SID global_sid_Builtin; -/********************************************************************************** - Check if this ACE has a SID in common with the token. -**********************************************************************************/ - -static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) -{ - size_t i; - - for (i = 0; i < token->num_sids; i++) { - if (sid_equal(&ace->trustee, &token->user_sids[i])) - return True; - } - - return False; -} - /********************************************************************************* Check an ACE against a SID. We return the remaining needed permission bits not yet granted. Zero means permission allowed (no more needed bits). @@ -332,119 +316,6 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, return False; } -/* Create a child security descriptor using another security descriptor as - the parent container. This child object can either be a container or - non-container object. */ - -SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, - BOOL child_container) -{ - SEC_DESC_BUF *sdb; - SEC_DESC *sd; - SEC_ACL *new_dacl, *the_acl; - SEC_ACE *new_ace_list = NULL; - unsigned int new_ace_list_ndx = 0, i; - size_t size; - - /* Currently we only process the dacl when creating the child. The - sacl should also be processed but this is left out as sacls are - not implemented in Samba at the moment.*/ - - the_acl = parent_ctr->dacl; - - if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) - return NULL; - - for (i = 0; the_acl && i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; - uint8 new_flags = 0; - BOOL inherit = False; - fstring sid_str; - - /* The OBJECT_INHERIT_ACE flag causes the ACE to be - inherited by non-container children objects. Container - children objects will inherit it as an INHERIT_ONLY - ACE. */ - - if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { - - if (!child_container) { - new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; - } else { - new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } - - inherit = True; - } - - /* The CONAINER_INHERIT_ACE flag means all child container - objects will inherit and use the ACE. */ - - if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { - if (!child_container) { - inherit = False; - } else { - new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; - } - } - - /* The INHERIT_ONLY_ACE is not used by the se_access_check() - function for the parent container, but is inherited by - all child objects as a normal ACE. */ - - if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - /* Move along, nothing to see here */ - } - - /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE - is inherited by child objects but not grandchildren - objects. We clear the object inherit and container - inherit flags in the inherited ACE. */ - - if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { - new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* Add ACE to ACE list */ - - if (!inherit) - continue; - - init_sec_access(&new_ace->info, ace->info.mask); - init_sec_ace(new_ace, &ace->trustee, ace->type, - new_ace->info, new_flags); - - sid_to_string(sid_str, &ace->trustee); - - DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " - " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, - ace->type, ace->flags, ace->info.mask, - sid_str, new_ace->type, new_ace->flags, - new_ace->info.mask)); - - new_ace_list_ndx++; - } - - /* Create child security descriptor to return */ - - new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); - - /* Use the existing user and group sids. I don't think this is - correct. Perhaps the user and group should be passed in as - parameters by the caller? */ - - sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - parent_ctr->owner_sid, - parent_ctr->grp_sid, - parent_ctr->sacl, - new_dacl, &size); - - sdb = make_sec_desc_buf(ctx, size, sd); - - return sdb; -} /******************************************************************* samr_make_sam_obj_sd diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index fbb393770d..50bbb4c72c 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -638,7 +638,7 @@ void print_guid(GUID *guid) Tallocs a duplicate SID. ********************************************************************/ -DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src) +DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src) { DOM_SID *dst; -- cgit