diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-06-01 10:39:30 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-06-01 10:39:30 +1000 |
commit | ba95882155db4f8c10725f47f70ae482d5343f9a (patch) | |
tree | 52c65ddfbcd81f3dcbb3b91183ae043b9c51acd5 | |
parent | 67b83d2489788f1899c253fdab554d0998f9c044 (diff) | |
parent | 14c13620345dfd9f1e18761f103aa66138bf8907 (diff) | |
download | samba-ba95882155db4f8c10725f47f70ae482d5343f9a.tar.gz samba-ba95882155db4f8c10725f47f70ae482d5343f9a.tar.bz2 samba-ba95882155db4f8c10725f47f70ae482d5343f9a.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
93 files changed, 3977 insertions, 2905 deletions
diff --git a/docs-xml/Samba3-HOWTO/TOSHARG-VFS.xml b/docs-xml/Samba3-HOWTO/TOSHARG-VFS.xml index b8bd3277a6..91e9712cb5 100644 --- a/docs-xml/Samba3-HOWTO/TOSHARG-VFS.xml +++ b/docs-xml/Samba3-HOWTO/TOSHARG-VFS.xml @@ -276,7 +276,7 @@ quotasettings: gid nolimit = no <para> <indexterm><primary>logging</primary></indexterm> - This auditing tool is more felxible than most people readily will recognize. There are a number of ways + This auditing tool is more flexible than most people will readily recognize. There are a number of ways by which useful logging information can be recorded. </para> diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index fe71b29117..d88edb177a 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -3,17 +3,21 @@ async socket syscalls Copyright (C) Volker Lendecke 2008 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the async_sock + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -77,6 +81,10 @@ static void async_send_handler(struct tevent_context *ev, tevent_req_data(req, struct async_send_state); state->sent = send(state->fd, state->buf, state->len, state->flags); + if ((state->sent == -1) && (errno == EINTR)) { + /* retry */ + return; + } if (state->sent == -1) { tevent_req_error(req, errno); return; @@ -144,6 +152,10 @@ static void async_recv_handler(struct tevent_context *ev, state->received = recv(state->fd, state->buf, state->len, state->flags); + if ((state->received == -1) && (errno == EINTR)) { + /* retry */ + return; + } if (state->received == -1) { tevent_req_error(req, errno); return; @@ -422,7 +434,11 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde, to_write += state->iov[i].iov_len; } - written = sys_writev(state->fd, state->iov, state->count); + written = writev(state->fd, state->iov, state->count); + if ((written == -1) && (errno = EINTR)) { + /* retry */ + return; + } if (written == -1) { tevent_req_error(req, errno); return; @@ -530,6 +546,10 @@ static void read_packet_handler(struct tevent_context *ev, nread = recv(state->fd, state->buf+state->nread, total-state->nread, 0); + if ((nread == -1) && (errno == EINTR)) { + /* retry */ + return; + } if (nread == -1) { tevent_req_error(req, errno); return; @@ -566,7 +586,7 @@ static void read_packet_handler(struct tevent_context *ev, return; } - tmp = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, total+more); + tmp = talloc_realloc(state, state->buf, uint8_t, total+more); if (tevent_req_nomem(tmp, req)) { return; } diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index a50e93238a..d47be30589 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -3,17 +3,21 @@ async socket operations Copyright (C) Volker Lendecke 2008 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the async_sock + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/lib/async_req/config.mk b/lib/async_req/config.mk index bf0fd6a2db..1f4b557ce4 100644 --- a/lib/async_req/config.mk +++ b/lib/async_req/config.mk @@ -1,3 +1,4 @@ [SUBSYSTEM::LIBASYNC_REQ] +PUBLIC_DEPENDENCIES = LIBREPLACE_NETWORK LIBASYNC_REQ_OBJ_FILES = $(addprefix ../lib/async_req/, async_sock.o) diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index a2def25814..233abe23f8 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -189,7 +189,7 @@ struct x32{ void SHA256_Update (SHA256_CTX *m, const void *v, size_t len) { - const unsigned char *p = v; + const unsigned char *p = (const unsigned char *)v; size_t old_sz = m->sz[0]; size_t offset; diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c index 1875dc3e4f..d7f7b0ba56 100644 --- a/lib/nss_wrapper/nss_wrapper.c +++ b/lib/nss_wrapper/nss_wrapper.c @@ -68,6 +68,11 @@ #define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS #endif +/* not all systems have getgrouplist */ +#ifndef HAVE_GETGROUPLIST +#define getgrouplist(user, group, groups, ngroups) 0 +#endif + /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support * for now */ #define REWRITE_CALLS @@ -90,6 +95,7 @@ #define real_initgroups_dyn initgroups_dyn */ #define real_initgroups initgroups +#define real_getgrouplist getgrouplist #define real_getgrnam getgrnam #define real_getgrnam_r getgrnam_r @@ -1222,3 +1228,81 @@ _PUBLIC_ void nwrap_endgrent(void) nwrap_files_endgrent(); } + +static int nwrap_files_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + struct group *grp; + gid_t *groups_tmp; + int count = 1; + const char *name_of_group = NULL; + + NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user)); + + groups_tmp = (gid_t *)malloc(count * sizeof(gid_t)); + if (!groups_tmp) { + NWRAP_ERROR(("%s:calloc failed\n",__location__)); + errno = ENOMEM; + return -1; + } + + memcpy(groups_tmp, &group, sizeof(gid_t)); + + grp = nwrap_getgrgid(group); + if (grp) { + name_of_group = grp->gr_name; + } + + nwrap_files_setgrent(); + while ((grp = nwrap_files_getgrent()) != NULL) { + int i = 0; + + NWRAP_VERBOSE(("%s: inspecting %s for group membership\n", + __location__, grp->gr_name)); + + for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { + + if ((strcmp(user, grp->gr_mem[i]) == 0) && + (strcmp(name_of_group, grp->gr_name) != 0)) { + + NWRAP_DEBUG(("%s: %s is member of %s\n", + __location__, user, grp->gr_name)); + + groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t)); + if (!groups_tmp) { + NWRAP_ERROR(("%s:calloc failed\n",__location__)); + errno = ENOMEM; + return -1; + } + + memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t)); + count++; + } + } + } + nwrap_files_endgrent(); + + NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n", + __location__, user, *ngroups)); + + if (*ngroups < count) { + *ngroups = count; + free(groups_tmp); + return -1; + } + + *ngroups = count; + memcpy(groups, groups_tmp, count * sizeof(gid_t)); + free(groups_tmp); + + return count; +} + +_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + if (!nwrap_enabled()) { + return real_getgrouplist(user, group, groups, ngroups); + } + + return nwrap_files_getgrouplist(user, group, groups, ngroups); +} + diff --git a/lib/nss_wrapper/nss_wrapper.h b/lib/nss_wrapper/nss_wrapper.h index 35a47348a8..5bcd42ead4 100644 --- a/lib/nss_wrapper/nss_wrapper.h +++ b/lib/nss_wrapper/nss_wrapper.h @@ -46,6 +46,7 @@ int nwrap_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); void nwrap_endpwent(void); int nwrap_initgroups(const char *user, gid_t group); +int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups); struct group *nwrap_getgrnam(const char *name); int nwrap_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); @@ -120,6 +121,11 @@ void nwrap_endgrent(void); #endif #define initgroups nwrap_initgroups +#ifdef getgrouplist +#undef getgrouplist +#endif +#define getgrouplist nwrap_getgrouplist + #ifdef getgrnam #undef getgrnam #endif diff --git a/lib/nss_wrapper/testsuite.c b/lib/nss_wrapper/testsuite.c new file mode 100644 index 0000000000..4f37354e12 --- /dev/null +++ b/lib/nss_wrapper/testsuite.c @@ -0,0 +1,332 @@ +/* + Unix SMB/CIFS implementation. + + local testing of the nss wrapper + + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "lib/replace/system/passwd.h" +#include "lib/nss_wrapper/nss_wrapper.h" + +static void print_passwd(struct passwd *pwd) +{ + printf("%s:%s:%lu:%lu:%s:%s:%s\n", + pwd->pw_name, + pwd->pw_passwd, + (unsigned long)pwd->pw_uid, + (unsigned long)pwd->pw_gid, + pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell); +} + + +static bool test_nwrap_getpwnam(struct torture_context *tctx, + const char *name) +{ + struct passwd *pwd; + + torture_comment(tctx, "Testing getpwnam: %s\n", name); + + pwd = getpwnam(name); + if (pwd) { + print_passwd(pwd); + } + + return pwd ? true : false; +} + +static bool test_nwrap_getpwuid(struct torture_context *tctx, + uid_t uid) +{ + struct passwd *pwd; + + torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid); + + pwd = getpwuid(uid); + if (pwd) { + print_passwd(pwd); + } + + return pwd ? true : false; +} + +static void print_group(struct group *grp) +{ + int i; + printf("%s:%s:%lu:", + grp->gr_name, + grp->gr_passwd, + (unsigned long)grp->gr_gid); + + if (!grp->gr_mem[0]) { + printf("\n"); + return; + } + + for (i=0; grp->gr_mem[i+1]; i++) { + printf("%s,", grp->gr_mem[i]); + } + printf("%s\n", grp->gr_mem[i]); +} + +static bool test_nwrap_getgrnam(struct torture_context *tctx, + const char *name) +{ + struct group *grp; + + torture_comment(tctx, "Testing getgrnam: %s\n", name); + + grp = getgrnam(name); + if (grp) { + print_group(grp); + } + + return grp ? true : false; +} + +static bool test_nwrap_getgrgid(struct torture_context *tctx, + gid_t gid) +{ + struct group *grp; + + torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid); + + grp = getgrgid(gid); + if (grp) { + print_group(grp); + } + + return grp ? true : false; +} + +static bool test_nwrap_enum_passwd(struct torture_context *tctx, + struct passwd **pwd_array_p, + size_t *num_pwd_p) +{ + struct passwd *pwd; + struct passwd *pwd_array = NULL; + size_t num_pwd = 0; + + torture_comment(tctx, "Testing setpwent\n"); + setpwent(); + + while ((pwd = getpwent()) != NULL) { + torture_comment(tctx, "Testing getpwent\n"); + + print_passwd(pwd); + if (pwd_array_p && num_pwd_p) { + pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1); + torture_assert(tctx, pwd_array, "out of memory"); + pwd_array[num_pwd].pw_name = talloc_strdup(tctx, pwd->pw_name); + pwd_array[num_pwd].pw_uid = pwd->pw_uid; + pwd_array[num_pwd].pw_gid = pwd->pw_gid; + num_pwd++; + } + } + + torture_comment(tctx, "Testing endpwent\n"); + endpwent(); + + if (pwd_array_p) { + *pwd_array_p = pwd_array; + } + if (num_pwd_p) { + *num_pwd_p = num_pwd; + } + + return true; +} + +static bool test_nwrap_passwd(struct torture_context *tctx) +{ + int i; + struct passwd *pwd; + size_t num_pwd; + + torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), + "failed to enumerate passwd"); + + for (i=0; i < num_pwd; i++) { + torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name), + "failed to call getpwnam for enumerated user"); + torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid), + "failed to call getpwuid for enumerated user"); + } + + return true; +} + +static bool test_nwrap_enum_group(struct torture_context *tctx, + struct group **grp_array_p, + size_t *num_grp_p) +{ + struct group *grp; + struct group *grp_array = NULL; + size_t num_grp = 0; + + torture_comment(tctx, "Testing setgrent\n"); + setgrent(); + + while ((grp = getgrent()) != NULL) { + torture_comment(tctx, "Testing getgrent\n"); + + print_group(grp); + if (grp_array_p && num_grp_p) { + grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1); + torture_assert(tctx, grp_array, "out of memory"); + grp_array[num_grp].gr_name = talloc_strdup(tctx, grp->gr_name); + grp_array[num_grp].gr_gid = grp->gr_gid; + num_grp++; + } + } + + torture_comment(tctx, "Testing endgrent\n"); + endgrent(); + + if (grp_array_p) { + *grp_array_p = grp_array; + } + if (num_grp_p) { + *num_grp_p = num_grp; + } + + + return true; +} + +static bool test_nwrap_group(struct torture_context *tctx) +{ + int i; + struct group *grp; + size_t num_grp; + + torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp), + "failed to enumerate group"); + + for (i=0; i < num_grp; i++) { + torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name), + "failed to call getgrnam for enumerated user"); + torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid), + "failed to call getgrgid for enumerated user"); + } + + return true; +} + +static bool test_nwrap_getgrouplist(struct torture_context *tctx, + const char *user, + gid_t gid, + gid_t **gids_p, + int *num_gids_p) +{ + int ret; + int num_groups = 0; + gid_t *groups = NULL; + + torture_comment(tctx, "Testing getgrouplist: %s\n", user); + + ret = getgrouplist(user, gid, NULL, &num_groups); + if (ret == -1 || num_groups != 0) { + + groups = talloc_array(tctx, gid_t, num_groups); + torture_assert(tctx, groups, "out of memory\n"); + + ret = getgrouplist(user, gid, groups, &num_groups); + } + + torture_assert(tctx, (ret != -1), "failed to call getgrouplist"); + + torture_comment(tctx, "%s is member in %d groups\n", user, num_groups); + + if (gids_p) { + *gids_p = groups; + } + if (num_gids_p) { + *num_gids_p = num_groups; + } + + return true; +} + +static bool test_nwrap_membership(struct torture_context *tctx) +{ + const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); + const char *old_group = getenv("NSS_WRAPPER_GROUP"); + struct passwd *pwd; + size_t num_pwd; + int i; + + if (!old_pwd || !old_group) { + torture_skip(tctx, "nothing to test\n"); + return true; + } + + torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), + "failed to enumerate passwd"); + + for (i=0; i < num_pwd; i++) { + + int num_user_groups = 0; + gid_t *user_groups = NULL; + int g; + + torture_assert(tctx, test_nwrap_getgrouplist(tctx, + pwd[i].pw_name, + pwd[i].pw_gid, + &user_groups, + &num_user_groups), + "failed to test getgrouplist"); + + for (g=0; g < num_user_groups; g++) { + torture_assert(tctx, test_nwrap_getgrgid(tctx, user_groups[g]), + "failed to find the group the user is a member of"); + } + } + + return true; +} + +static bool test_nwrap_env(struct torture_context *tctx) +{ + const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); + const char *old_group = getenv("NSS_WRAPPER_GROUP"); + + if (!old_pwd || !old_group) { + torture_skip(tctx, "nothing to test\n"); + return true; + } + + torture_assert(tctx, test_nwrap_passwd(tctx), + "failed to test users"); + torture_assert(tctx, test_nwrap_group(tctx), + "failed to test groups"); + + return true; +} + +struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "NSS-WRAPPER"); + + torture_suite_add_simple_test(suite, "env", test_nwrap_env); + torture_suite_add_simple_test(suite, "membership", test_nwrap_membership); + + return suite; +} diff --git a/lib/replace/system/config.m4 b/lib/replace/system/config.m4 index 5c9b53d5c5..e2196586ad 100644 --- a/lib/replace/system/config.m4 +++ b/lib/replace/system/config.m4 @@ -116,6 +116,7 @@ AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, si #include <unistd.h> #include <grp.h> ]) +AC_CHECK_FUNCS(getgrouplist) # locale AC_CHECK_HEADERS(ctype.h locale.h) diff --git a/lib/util/config.mk b/lib/util/config.mk index 1b620d1464..3ae8a22780 100644 --- a/lib/util/config.mk +++ b/lib/util/config.mk @@ -28,7 +28,8 @@ LIBSAMBA-UTIL_OBJ_FILES = $(addprefix $(libutilsrcdir)/, \ rbtree.o \ talloc_stack.o \ smb_threads.o \ - params.o) + params.o \ + util_id.o) PUBLIC_HEADERS += $(addprefix $(libutilsrcdir)/, util.h \ dlinklist.h \ diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c index b89d5cd4d4..0a8c4c6b30 100644 --- a/lib/util/tevent_unix.c +++ b/lib/util/tevent_unix.c @@ -3,17 +3,21 @@ Wrap unix errno around tevent_req Copyright (C) Volker Lendecke 2009 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the tevent_unix + ** helper library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h index dc3ffaef33..bc2cea9199 100644 --- a/lib/util/tevent_unix.h +++ b/lib/util/tevent_unix.h @@ -3,17 +3,21 @@ Wrap unix errno around tevent_req Copyright (C) Volker Lendecke 2009 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the tevent_unix + ** helper library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/lib/util/util.h b/lib/util/util.h index dab5ff9360..20050d2f0a 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -817,4 +817,16 @@ bool unmap_file(void *start, size_t size); void print_asc(int level, const uint8_t *buf,int len); +/** + * Add an id to an array of ids. + * + * num should be a pointer to an integer that holds the current + * number of elements in ids. It will be updated by this function. + */ + +bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, + uid_t **uids, size_t *num_uids); +bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, + gid_t **gids, size_t *num_gids); + #endif /* _SAMBA_UTIL_H_ */ diff --git a/lib/util/util_id.c b/lib/util/util_id.c new file mode 100644 index 0000000000..8744ce4e4e --- /dev/null +++ b/lib/util/util_id.c @@ -0,0 +1,88 @@ +/* + Unix SMB/CIFS implementation. + + Helper routines for uid and gid arrays + + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" + +/**************************************************************************** + Add a gid to an array of gids if it's not already there. +****************************************************************************/ + +bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, + gid_t **gids, size_t *num_gids) +{ + int i; + + if ((*num_gids != 0) && (*gids == NULL)) { + /* + * A former call to this routine has failed to allocate memory + */ + return false; + } + + for (i=0; i<*num_gids; i++) { + if ((*gids)[i] == gid) { + return true; + } + } + + *gids = talloc_realloc(mem_ctx, *gids, gid_t, *num_gids+1); + if (*gids == NULL) { + *num_gids = 0; + return false; + } + + (*gids)[*num_gids] = gid; + *num_gids += 1; + return true; +} + +/**************************************************************************** + Add a uid to an array of uids if it's not already there. +****************************************************************************/ + +bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, + uid_t **uids, size_t *num_uids) +{ + int i; + + if ((*num_uids != 0) && (*uids == NULL)) { + /* + * A former call to this routine has failed to allocate memory + */ + return false; + } + + for (i=0; i<*num_uids; i++) { + if ((*uids)[i] == uid) { + return true; + } + } + + *uids = talloc_realloc(mem_ctx, *uids, uid_t, *num_uids+1); + if (*uids == NULL) { + *num_uids = 0; + return false; + } + + (*uids)[*num_uids] = uid; + *num_uids += 1; + return true; +} diff --git a/librpc/gen_ndr/security.h b/librpc/gen_ndr/security.h index 16635f0bb8..d1dcbe552a 100644 --- a/librpc/gen_ndr/security.h +++ b/librpc/gen_ndr/security.h @@ -121,17 +121,21 @@ #define SID_BUILTIN_REPLICATOR ( "S-1-5-32-552" ) #define SID_BUILTIN_RAS_SERVERS ( "S-1-5-32-553" ) #define SID_BUILTIN_PREW2K ( "S-1-5-32-554" ) +#define SID_BUILTIN_REMOTE_DESKTOP_USERS ( "S-1-5-32-555" ) +#define SID_BUILTIN_NETWORK_CONF_OPERATORS ( "S-1-5-32-556" ) #define DOMAIN_RID_LOGON ( 9 ) #define DOMAIN_RID_ADMINISTRATOR ( 500 ) #define DOMAIN_RID_GUEST ( 501 ) +#define DOMAIN_RID_KRBTGT ( 502 ) #define DOMAIN_RID_ADMINS ( 512 ) #define DOMAIN_RID_USERS ( 513 ) -#define DOMAIN_RID_KRBTGT ( 514 ) +#define DOMAIN_RID_GUESTS ( 514 ) #define DOMAIN_RID_DOMAIN_MEMBERS ( 515 ) #define DOMAIN_RID_DCS ( 516 ) #define DOMAIN_RID_CERT_ADMINS ( 517 ) #define DOMAIN_RID_SCHEMA_ADMINS ( 518 ) #define DOMAIN_RID_ENTERPRISE_ADMINS ( 519 ) +#define DOMAIN_RID_POLICY_ADMINS ( 520 ) #define NT4_ACL_REVISION ( SECURITY_ACL_REVISION_NT4 ) #define SD_REVISION ( SECURITY_DESCRIPTOR_REVISION_1 ) struct dom_sid { diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index 9e47ff45fc..9728c7fb07 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -219,19 +219,23 @@ interface security const string SID_BUILTIN_REPLICATOR = "S-1-5-32-552"; const string SID_BUILTIN_RAS_SERVERS = "S-1-5-32-553"; const string SID_BUILTIN_PREW2K = "S-1-5-32-554"; + const string SID_BUILTIN_REMOTE_DESKTOP_USERS = "S-1-5-32-555"; + const string SID_BUILTIN_NETWORK_CONF_OPERATORS = "S-1-5-32-556"; /* well-known domain RIDs */ const int DOMAIN_RID_LOGON = 9; const int DOMAIN_RID_ADMINISTRATOR = 500; const int DOMAIN_RID_GUEST = 501; + const int DOMAIN_RID_KRBTGT = 502; const int DOMAIN_RID_ADMINS = 512; const int DOMAIN_RID_USERS = 513; - const int DOMAIN_RID_KRBTGT = 514; + const int DOMAIN_RID_GUESTS = 514; const int DOMAIN_RID_DOMAIN_MEMBERS = 515; const int DOMAIN_RID_DCS = 516; const int DOMAIN_RID_CERT_ADMINS = 517; const int DOMAIN_RID_SCHEMA_ADMINS = 518; const int DOMAIN_RID_ENTERPRISE_ADMINS = 519; + const int DOMAIN_RID_POLICY_ADMINS = 520; /* diff --git a/nsswitch/config.mk b/nsswitch/config.mk index 3a4f054d1f..264032e530 100644 --- a/nsswitch/config.mk +++ b/nsswitch/config.mk @@ -26,7 +26,11 @@ PRIVATE_DEPENDENCIES = \ LIBCLI_AUTH \ LIBPOPT \ POPT_SAMBA \ - LIBWINBIND-CLIENT + LIBWINBIND-CLIENT \ + LIBWBCLIENT \ + LIBTEVENT \ + UTIL_TEVENT \ + LIBASYNC_REQ # End BINARY nsstest ################################# diff --git a/nsswitch/libwbclient/config.mk b/nsswitch/libwbclient/config.mk new file mode 100644 index 0000000000..ffdab159f8 --- /dev/null +++ b/nsswitch/libwbclient/config.mk @@ -0,0 +1,15 @@ +[SUBSYSTEM::LIBWBCLIENT] +PUBLIC_DEPENDENCIES = LIBASYNC_REQ \ + LIBTEVENT \ + LIBTALLOC \ + UTIL_TEVENT + +LIBWBCLIENT_OBJ_FILES = $(addprefix $(libwbclientsrcdir)/, wbc_async.o \ + wbc_guid.o \ + wbc_idmap.o \ + wbclient.o \ + wbc_pam.o \ + wbc_pwd.o \ + wbc_sid.o \ + wbc_util.o \ + wb_reqtrans.o ) diff --git a/nsswitch/libwbclient/libwbclient.h b/nsswitch/libwbclient/libwbclient.h index 74cba7e796..5a25cf462c 100644 --- a/nsswitch/libwbclient/libwbclient.h +++ b/nsswitch/libwbclient/libwbclient.h @@ -36,6 +36,7 @@ /* Public headers */ #include "wbclient.h" +#include "wbc_async.h" /* Private headers */ diff --git a/source3/lib/wb_reqtrans.c b/nsswitch/libwbclient/wb_reqtrans.c index 55883ba8c7..84ed7198f2 100644 --- a/source3/lib/wb_reqtrans.c +++ b/nsswitch/libwbclient/wb_reqtrans.c @@ -5,25 +5,41 @@ Copyright (C) Volker Lendecke 2008 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the wbclient + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "includes.h" -#include "wbc_async.h" - +#include "replace.h" +#include "system/filesys.h" +#include "system/network.h" +#include <talloc.h> +#include <tevent.h> +struct fd_event; +struct event_context; +#include "lib/async_req/async_sock.h" +#include "lib/util/tevent_unix.h" +#include "nsswitch/winbind_struct_protocol.h" +#include "nsswitch/libwbclient/wbclient.h" +#include "nsswitch/libwbclient/wbc_async.h" + +#ifdef DBGC_CLASS #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +#endif struct req_read_state { struct winbindd_request *wb_req; diff --git a/source3/lib/wbclient.c b/nsswitch/libwbclient/wbc_async.c index 164cfc9691..5f985f9d5a 100644 --- a/source3/lib/wbclient.c +++ b/nsswitch/libwbclient/wbc_async.c @@ -3,22 +3,35 @@ Infrastructure for async winbind requests Copyright (C) Volker Lendecke 2008 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the wbclient + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "includes.h" -#include "wbc_async.h" +#include "replace.h" +#include "system/filesys.h" +#include "system/network.h" +#include <talloc.h> +#include <tevent.h> +struct fd_event; +struct event_context; +#include "lib/async_req/async_sock.h" +#include "nsswitch/winbind_struct_protocol.h" +#include "nsswitch/libwbclient/wbclient.h" +#include "nsswitch/libwbclient/wbc_async.h" wbcErr map_wbc_err_from_errno(int error) { @@ -75,6 +88,7 @@ struct wb_context { struct tevent_queue *queue; int fd; bool is_priv; + const char *dir; }; static int make_nonstd_fd(int fd) @@ -166,7 +180,10 @@ static int make_safe_fd(int fd) return -1; } -struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) +/* Just put a prototype to avoid moving the whole function around */ +static const char *winbindd_socket_dir(void); + +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir) { struct wb_context *result; @@ -181,6 +198,16 @@ struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) } result->fd = -1; result->is_priv = false; + + if (dir != NULL) { + result->dir = talloc_strdup(result, dir); + } else { + result->dir = winbindd_socket_dir(); + } + if (result->dir == NULL) { + TALLOC_FREE(result); + return NULL; + } return result; } @@ -338,7 +365,7 @@ static struct tevent_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, wb_ctx->fd = -1; } - subreq = wb_connect_send(state, ev, wb_ctx, winbindd_socket_dir()); + subreq = wb_connect_send(state, ev, wb_ctx, wb_ctx->dir); if (subreq == NULL) { goto fail; } diff --git a/source3/include/wbc_async.h b/nsswitch/libwbclient/wbc_async.h index 57625d5baf..607dd9de28 100644 --- a/source3/include/wbc_async.h +++ b/nsswitch/libwbclient/wbc_async.h @@ -1,28 +1,36 @@ /* Unix SMB/CIFS implementation. Headers for the async winbind client library - Copyright (C) Kai Blin 2009 + Copyright (C) Volker Lendecke 2008 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the wbclient + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _WBC_ASYNC_H_ #define _WBC_ASYNC_H_ +#include <talloc.h> +#include <tevent.h> #include "nsswitch/libwbclient/wbclient.h" struct wb_context; +struct winbindd_request; +struct winbindd_response; struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -30,7 +38,7 @@ struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct winbindd_request *wb_req); wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct winbindd_response **presponse); -struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx); +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir); /* Definitions from wb_reqtrans.c */ wbcErr map_wbc_err_from_errno(int error); diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c index 61ce2a12d2..eeb798a78c 100644 --- a/nsswitch/libwbclient/wbc_pam.c +++ b/nsswitch/libwbclient/wbc_pam.c @@ -255,7 +255,7 @@ done: } static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, + struct winbindd_response *resp, struct wbcLogonUserInfo **_i) { wbcErr wbc_status = WBC_ERR_SUCCESS; diff --git a/nsswitch/libwbclient/wbclient.c b/nsswitch/libwbclient/wbclient.c index f5c72315f2..77b7e12d04 100644 --- a/nsswitch/libwbclient/wbclient.c +++ b/nsswitch/libwbclient/wbclient.c @@ -22,6 +22,8 @@ /* Required Headers */ +#include "lib/talloc/talloc.h" +#include "lib/tevent/tevent.h" #include "libwbclient.h" /* From wb_common.c */ diff --git a/nsswitch/libwbclient/wbclient_internal.h b/nsswitch/libwbclient/wbclient_internal.h index fc03c5409b..2d103ab3df 100644 --- a/nsswitch/libwbclient/wbclient_internal.h +++ b/nsswitch/libwbclient/wbclient_internal.h @@ -28,5 +28,4 @@ wbcErr wbcRequestResponse(int cmd, struct winbindd_request *request, struct winbindd_response *response); - #endif /* _WBCLIENT_INTERNAL_H */ diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h index 11b2069c3a..1785c30906 100644 --- a/nsswitch/winbind_struct_protocol.h +++ b/nsswitch/winbind_struct_protocol.h @@ -15,6 +15,11 @@ #define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) #endif +#ifndef FSTRING_LEN +#define FSTRING_LEN 256 +typedef char fstring[FSTRING_LEN]; +#endif + #ifndef _WINBINDD_NTDOM_H #define _WINBINDD_NTDOM_H diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 95d2a8253f..4723fd6909 100644 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -542,6 +542,7 @@ $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false open(GROUP, ">$nss_wrapper_group") or die("Unable to open $nss_wrapper_group"); print GROUP "nobody:x:65533: nogroup:x:65534:nobody +root:x:65532: $unix_name-group:x:$unix_gids[0]: "; close(GROUP); diff --git a/source3/Makefile.in b/source3/Makefile.in index 2b30b4a5bd..9c87c6776a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -355,7 +355,7 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \ ../lib/util/genrand.o ../lib/util/util_net.o \ ../lib/util/become_daemon.o ../lib/util/system.o \ ../lib/util/tevent_unix.o ../lib/util/tevent_ntstatus.o \ - ../lib/util/smb_threads.o + ../lib/util/smb_threads.o ../lib/util/util_id.o CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \ ../lib/crypto/hmacmd5.o ../lib/crypto/arcfour.o \ @@ -372,6 +372,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/interface.o lib/pidfile.o \ lib/system.o lib/sendfile.o lib/recvfile.o lib/time.o \ lib/username.o \ + lib/ads_flags.o \ lib/util_pw.o lib/access.o lib/smbrun.o \ lib/bitmap.o lib/dprintf.o $(UTIL_REG_OBJ) \ lib/wins_srv.o \ @@ -992,7 +993,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ - lib/wb_reqtrans.o lib/wbclient.o \ + @LIBWBCLIENT_STATIC@ \ $(LIBNDR_GEN_OBJ0) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \ @@ -1186,7 +1187,7 @@ TDBTOOL_OBJ = @tdbdir@/tools/tdbtool.o $(LIBREPLACE_OBJ) \ TDBDUMP_OBJ = @tdbdir@/tools/tdbdump.o $(LIBREPLACE_OBJ) \ $(SOCKET_WRAPPER_OBJ) -TDBTORTURE_OBJ = @tdbdir@/tools/tdbtorture.o $(LIBREPLACE_OBJ) \ +TDBTORTURE_OBJ = @tdbdir@/tools/tdbtorture.o $(LIBTDB_OBJ) \ $(SOCKET_WRAPPER_OBJ) @@ -1876,7 +1877,10 @@ LIBWBCLIENT_OBJ0 = ../nsswitch/libwbclient/wbclient.o \ ../nsswitch/libwbclient/wbc_idmap.o \ ../nsswitch/libwbclient/wbc_sid.o \ ../nsswitch/libwbclient/wbc_guid.o \ - ../nsswitch/libwbclient/wbc_pam.o + ../nsswitch/libwbclient/wbc_pam.o \ + ../nsswitch/libwbclient/wb_reqtrans.o \ + ../nsswitch/libwbclient/wbc_async.o + LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) \ $(WBCOMMON_OBJ) \ $(LIBREPLACE_OBJ) @@ -1887,7 +1891,8 @@ LIBWBCLIENT_SHARED_TARGET_SONAME=$(LIBWBCLIENT_SHARED_TARGET).$(LIBWBCLIENT_SOVE LIBWBCLIENT_STATIC_TARGET=@LIBWBCLIENT_STATIC_TARGET@ LIBWBCLIENT=@LIBWBCLIENT_STATIC@ @LIBWBCLIENT_SHARED@ LIBWBCLIENT_SYMS=$(srcdir)/exports/libwbclient.@SYMSEXT@ -LIBWBCLIENT_HEADERS=$(srcdir)/../nsswitch/libwbclient/wbclient.h +LIBWBCLIENT_HEADERS=$(srcdir)/../nsswitch/libwbclient/wbclient.h \ + $(srcdir)/../nsswitch/libwbclient/wbc_async.h $(LIBWBCLIENT_SYMS): $(LIBWBCLIENT_HEADERS) @$(MKSYMS_SH) $(AWK) $@ $(LIBWBCLIENT_HEADERS) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index a27025fc8d..9d29987c0d 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -208,21 +208,15 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n", client_domain, smb_name, wksta_name)); - /* don't allow "" as a domain, fixes a Win9X bug - where it doens't supply a domain for logon script - 'net use' commands. */ - - if ( *client_domain ) - domain = client_domain; - else - domain = lp_workgroup(); + domain = client_domain; /* If you connect to a Windows domain member using a bogus domain name, * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if * the Windows box is a DC the name will become DOMAIN\user and be * authenticated against AD, if the Windows box is a member server but * not a DC the name will become WORKSTATION\user. A standalone - * non-domain member box will also map to WORKSTATION\user. */ + * non-domain member box will also map to WORKSTATION\user. + * This also deals with the client passing in a "" domain */ if (!is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) ) diff --git a/source3/client/client.c b/source3/client/client.c index 2edeb1ae2b..0852652725 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2872,7 +2872,7 @@ static int cmd_chmod(void) return 1; } - if (!cli_unix_chmod(targetcli, targetname, mode)) { + if (!NT_STATUS_IS_OK(cli_posix_chmod(targetcli, targetname, mode))) { d_printf("%s chmod file %s 0%o\n", cli_errstr(targetcli), src, (unsigned int)mode); return 1; @@ -3037,23 +3037,22 @@ static int cmd_getfacl(void) return 1; } - if (!cli_unix_stat(targetcli, targetname, &sbuf)) { + if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) { d_printf("%s getfacl doing a stat on file %s\n", cli_errstr(targetcli), src); return 1; } - if (!cli_unix_getfacl(targetcli, targetname, &rb_size, &retbuf)) { + if (!NT_STATUS_IS_OK(cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf))) { d_printf("%s getfacl file %s\n", cli_errstr(targetcli), src); return 1; } /* ToDo : Print out the ACL values. */ - if (SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION || rb_size < 6) { + if (rb_size < 6 || SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION) { d_printf("getfacl file %s, unknown POSIX acl version %u.\n", src, (unsigned int)CVAL(retbuf,0) ); - SAFE_FREE(retbuf); return 1; } @@ -3064,8 +3063,6 @@ static int cmd_getfacl(void) src, (unsigned int)(SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)), (unsigned int)rb_size); - - SAFE_FREE(retbuf); return 1; } @@ -3150,7 +3147,6 @@ static int cmd_getfacl(void) d_printf("%s\n", perms_to_string(permstring, perms)); } - SAFE_FREE(retbuf); return 0; } @@ -3192,7 +3188,7 @@ static int cmd_stat(void) return 1; } - if (!cli_unix_stat(targetcli, targetname, &sbuf)) { + if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) { d_printf("%s stat file %s\n", cli_errstr(targetcli), src); return 1; @@ -3296,7 +3292,7 @@ static int cmd_chown(void) return 1; } - if (!cli_unix_chown(targetcli, targetname, uid, gid)) { + if (!NT_STATUS_IS_OK(cli_posix_chown(targetcli, targetname, uid, gid))) { d_printf("%s chown file %s uid=%d, gid=%d\n", cli_errstr(targetcli), src, (int)uid, (int)gid); return 1; diff --git a/source3/include/proto.h b/source3/include/proto.h index 2217b3315b..81d254f1ff 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1088,8 +1088,6 @@ struct user_auth_info *get_cmdline_auth_info_copy(TALLOC_CTX *mem_ctx, const struct user_auth_info *info); bool set_cmdline_auth_info_machine_account_creds(struct user_auth_info *auth_info); void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info); -bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, - gid_t **gids, size_t *num_gids); bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf); bool socket_exist(const char *fname); bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st); @@ -2361,10 +2359,46 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli, const char *newname); uint32_t unix_perms_to_wire(mode_t perms); mode_t wire_perms_to_unix(uint32_t perms); -bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf); -bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf); -bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode); -bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid); +struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname); +NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + size_t *prb_size, + char **retbuf); +NTSTATUS cli_posix_getfacl(struct cli_state *cli, + const char *fname, + TALLOC_CTX *mem_ctx, + size_t *prb_size, + char **retbuf); +struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname); +NTSTATUS cli_posix_stat_recv(struct tevent_req *req, + SMB_STRUCT_STAT *sbuf); +NTSTATUS cli_posix_stat(struct cli_state *cli, + const char *fname, + SMB_STRUCT_STAT *sbuf); +struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + mode_t mode); +NTSTATUS cli_posix_chmod_recv(struct tevent_req *req); +NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode); +struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uid_t uid, + gid_t gid); +NTSTATUS cli_posix_chown_recv(struct tevent_req *req); +NTSTATUS cli_posix_chown(struct cli_state *cli, + const char *fname, + uid_t uid, + gid_t gid); struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, @@ -2408,7 +2442,13 @@ struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx, const char *dname); NTSTATUS cli_rmdir_recv(struct tevent_req *req); NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname); -int cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag); +struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + bool flag); +NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req); +NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag); struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, @@ -2967,6 +3007,7 @@ NTSTATUS dos_to_ntstatus(uint8 eclass, uint32 ecode); void ntstatus_to_dos(NTSTATUS ntstatus, uint8 *eclass, uint32 *ecode); NTSTATUS werror_to_ntstatus(WERROR error); WERROR ntstatus_to_werror(NTSTATUS error); +NTSTATUS map_nt_error_from_wbcErr(wbcErr wbc_err); NTSTATUS map_nt_error_from_gss(uint32 gss_maj, uint32 minor); /* The following definitions come from libsmb/namecache.c */ @@ -4278,7 +4319,7 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp); void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val); int lp_min_receive_file_size(void); char* lp_perfcount_module(void); - +void lp_set_passdb_backend(const char *backend); /* The following definitions come from param/util.c */ diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index c28d43d53b..8710e77f3d 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -2,20 +2,20 @@ Unix SMB/CIFS mplementation. LDAP protocol helper functions for SAMBA Copyright (C) Gerald Carter 2001-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 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - + */ #ifndef _SMBLDAP_H @@ -214,6 +214,9 @@ char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry, const char *attribute, TALLOC_CTX *mem_ctx); +bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *msg, const char *attrib, + DATA_BLOB *blob); bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib, struct dom_sid *sid); void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result); diff --git a/source3/lib/ads_flags.c b/source3/lib/ads_flags.c new file mode 100644 index 0000000000..a8fa062f2a --- /dev/null +++ b/source3/lib/ads_flags.c @@ -0,0 +1,150 @@ +/* + Unix SMB/CIFS implementation. + ads (active directory) utility library + + Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Andrew Tridgell 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" + +/* +translated the ACB_CTRL Flags to UserFlags (userAccountControl) +*/ +uint32 ads_acb2uf(uint32 acb) +{ + uint32 uf = 0x00000000; + + if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE; + if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED; + if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD; + if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT; + if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT; + if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT; + if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT; + if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT; + if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT; + if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD; + if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT; + if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY; + if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED; + if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION; + if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH; + if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED; + if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED; + if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED; + + return uf; +} + +/* +translated the UserFlags (userAccountControl) to ACB_CTRL Flags +*/ +uint32 ads_uf2acb(uint32 uf) +{ + uint32 acb = 0x00000000; + + if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED; + if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ; + if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ; + if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS; + if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP; + if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK; + if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY; + if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED; + if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION; + if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH; + if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD; + if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED; + if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED; + + switch (uf & UF_ACCOUNT_TYPE_MASK) + { + case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break; + case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break; + case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break; + case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break; + case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break; + /*Fix Me: what should we do here? */ + default: acb |= ACB_NORMAL;break; + } + + return acb; +} + +/* +get the accountType from the UserFlags +*/ +uint32 ads_uf2atype(uint32 uf) +{ + uint32 atype = 0x00000000; + + if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; + else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; + else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; + else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; + else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST; + + return atype; +} + +/* +get the accountType from the groupType +*/ +uint32 ads_gtype2atype(uint32 gtype) +{ + uint32 atype = 0x00000000; + + switch(gtype) { + case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: + atype = ATYPE_SECURITY_LOCAL_GROUP; + break; + case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: + atype = ATYPE_SECURITY_LOCAL_GROUP; + break; + case GTYPE_SECURITY_GLOBAL_GROUP: + atype = ATYPE_SECURITY_GLOBAL_GROUP; + break; + + case GTYPE_DISTRIBUTION_GLOBAL_GROUP: + atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP; + break; + case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP: + atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP; + break; + case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP: + atype = ATYPE_DISTRIBUTION_LOCAL_GROUP; + break; + } + + return atype; +} + +/* turn a sAMAccountType into a SID_NAME_USE */ +enum lsa_SidType ads_atype_map(uint32 atype) +{ + switch (atype & 0xF0000000) { + case ATYPE_GLOBAL_GROUP: + return SID_NAME_DOM_GRP; + case ATYPE_SECURITY_LOCAL_GROUP: + return SID_NAME_ALIAS; + case ATYPE_ACCOUNT: + return SID_NAME_USER; + default: + DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); + } + return SID_NAME_UNKNOWN; +} diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index b6921c329c..4833b96c5f 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -6,20 +6,20 @@ Copyright (C) Shahms King 2001 Copyright (C) Andrew Bartlett 2002-2003 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 the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - + */ #include "includes.h" @@ -217,13 +217,13 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { 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; } @@ -236,7 +236,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { { const char **names; int i = 0; - + while ( table[i].attrib != LDAP_ATTR_LIST_END ) i++; i++; @@ -253,7 +253,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { i++; } names[i] = NULL; - + return names; } @@ -266,25 +266,25 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { int max_len) { 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] = [<does not exist>]\n", attribute)); - + return False; } - + if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (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)); @@ -389,23 +389,42 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { return result; } - bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib, - struct dom_sid *sid) + bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *msg, const char *attrib, + DATA_BLOB *blob) { struct berval **values; - bool ret = False; values = ldap_get_values_len(ld, msg, attrib); - if (!values) { return false; } - if (values[0] != NULL) { - ret = sid_parse(values[0]->bv_val, values[0]->bv_len, sid); + if (ldap_count_values_len(values) != 1) { + DEBUG(10, ("Expected one value for %s, got %d\n", attrib, + ldap_count_values_len(values))); + return false; } + *blob = data_blob_talloc(mem_ctx, values[0]->bv_val, + values[0]->bv_len); ldap_value_free_len(values); + + return (blob->data != NULL); +} + + bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib, + struct dom_sid *sid) +{ + DATA_BLOB blob; + bool ret; + + if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib, + &blob)) { + return false; + } + ret = sid_parse((char *)blob.data, blob.length, sid); + TALLOC_FREE(blob.data); return ret; } @@ -514,7 +533,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { for (; mods[i]->mod_values[j] != NULL; j++); } mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2); - + if (mods[i]->mod_values == NULL) { smb_panic("smbldap_set_mod: out of memory!"); /* notreached. */ @@ -524,8 +543,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { smb_panic("smbldap_set_mod: String conversion failure!"); /* notreached. */ } - - + mods[i]->mod_values[j] = SMB_STRDUP(utf8_value); TALLOC_FREE(utf8_value); SMB_ASSERT(mods[i]->mod_values[j] != NULL); @@ -561,9 +579,9 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { } /* all of our string attributes are case insensitive */ - + if (existed && newval && (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... */ @@ -582,7 +600,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { /* This will also allow modifying single valued attributes * in Novell NDS. In NDS you have to first remove attribute and then * you could add new value */ - + DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval)); smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); } @@ -640,7 +658,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) { struct smbldap_state *tmp_ldap_state; struct smbldap_state_lookup *t; - + if ((tmp_ldap_state = smbldap_find_state(ld))) { SMB_ASSERT(tmp_ldap_state == smbldap_state); return; @@ -648,7 +666,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) t = SMB_XMALLOC_P(struct smbldap_state_lookup); ZERO_STRUCTP(t); - + DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *); t->ld = ld; t->smbldap_state = smbldap_state; @@ -663,11 +681,11 @@ int smb_ldap_start_tls(LDAP *ldap_struct, int version) #ifdef LDAP_OPT_X_TLS int rc; #endif - + if (lp_ldap_ssl() != LDAP_SSL_START_TLS) { return LDAP_SUCCESS; } - + #ifdef LDAP_OPT_X_TLS if (version != LDAP_VERSION3) { DEBUG(0, ("Need LDAPv3 for Start TLS\n")); @@ -697,9 +715,9 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri) int rc; DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri)); - + #ifdef HAVE_LDAP_INITIALIZE - + rc = ldap_initialize(ldap_struct, uri); if (rc) { DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); @@ -721,9 +739,9 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri) if ( strnequal( uri, "URL:", 4 ) ) { uri += 4; } - + sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port); - + if (port == 0) { if (strequal(protocol, "ldap")) { port = LDAP_PORT; @@ -733,12 +751,12 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri) 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; @@ -746,7 +764,7 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri) { 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")); @@ -792,7 +810,7 @@ int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version) { int version; int rc; - + /* assume the worst */ *new_version = LDAP_VERSION2; @@ -812,7 +830,7 @@ int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version) if (rc) { return rc; } - + *new_version = LDAP_VERSION3; return LDAP_SUCCESS; } @@ -875,7 +893,7 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state) if (rc) { return rc; } - + DEBUG(2, ("smbldap_open_connection: connection opened\n")); return rc; } @@ -890,11 +908,11 @@ 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); if (*credp) { @@ -923,7 +941,7 @@ static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, } GetTimeOfDay(&ldap_state->last_rebind); - + return 0; } #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ @@ -998,7 +1016,6 @@ static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, 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)*/ @@ -1039,7 +1056,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ /* 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_state->bind_dn)); @@ -1175,17 +1192,17 @@ 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(ldap_state->ldap_struct); 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; } @@ -1279,7 +1296,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, size_t converted_size; SMB_ASSERT(ldap_state); - + DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], " "scope => [%d]\n", base, filter, scope)); @@ -1506,7 +1523,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at } } } - + TALLOC_FREE(utf8_dn); return rc; } @@ -1518,7 +1535,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs char *utf8_dn; time_t endtime = time(NULL)+lp_ldap_timeout(); size_t converted_size; - + SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_add: dn => [%s]\n", dn )); @@ -1550,7 +1567,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs } } } - + TALLOC_FREE(utf8_dn); return rc; } @@ -1562,7 +1579,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) char *utf8_dn; time_t endtime = time(NULL)+lp_ldap_timeout(); size_t converted_size; - + SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_delete: dn => [%s]\n", dn )); @@ -1594,7 +1611,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) } } } - + TALLOC_FREE(utf8_dn); return rc; } @@ -1607,7 +1624,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, int rc = LDAP_SERVER_DOWN; int attempts = 0; time_t endtime = time(NULL)+lp_ldap_timeout(); - + if (!ldap_state) return (-1); @@ -1636,7 +1653,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, } } } - + return rc; } @@ -1664,7 +1681,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx, DEBUG(10,("ldap connection not connected...\n")); return; } - + if ((state->last_use+SMBLDAP_IDLE_TIME) > now.tv_sec) { DEBUG(10,("ldap connection not idle...\n")); @@ -1675,7 +1692,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx, private_data); return; } - + DEBUG(7,("ldap connection idle...closing connection\n")); smbldap_close(state); } @@ -1687,7 +1704,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx, 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)); } diff --git a/source3/lib/util.c b/source3/lib/util.c index 8e67edeae6..b85f29e136 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -495,39 +495,6 @@ void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info) TALLOC_FREE(frame); } -/**************************************************************************** - Add a gid to an array of gids if it's not already there. -****************************************************************************/ - -bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, - gid_t **gids, size_t *num_gids) -{ - int i; - - if ((*num_gids != 0) && (*gids == NULL)) { - /* - * A former call to this routine has failed to allocate memory - */ - return False; - } - - for (i=0; i<*num_gids; i++) { - if ((*gids)[i] == gid) { - return True; - } - } - - *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1); - if (*gids == NULL) { - *num_gids = 0; - return False; - } - - (*gids)[*num_gids] = gid; - *num_gids += 1; - return True; -} - /******************************************************************* Check if a file exists - call vfs_file_exist for samba files. ********************************************************************/ diff --git a/source3/libads/ads_utils.c b/source3/libads/ads_utils.c index fc2ea9d9fd..213242c223 100644 --- a/source3/libads/ads_utils.c +++ b/source3/libads/ads_utils.c @@ -1,154 +1,26 @@ -/* +/* Unix SMB/CIFS implementation. ads (active directory) utility library - + Copyright (C) Stefan (metze) Metzmacher 2002 Copyright (C) Andrew Tridgell 2001 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -/* -translated the ACB_CTRL Flags to UserFlags (userAccountControl) -*/ -uint32 ads_acb2uf(uint32 acb) -{ - uint32 uf = 0x00000000; - - if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE; - if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED; - if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD; - if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT; - if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT; - if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT; - if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT; - if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT; - if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT; - if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD; - if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT; - if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY; - if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED; - if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION; - if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH; - if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED; - if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED; - if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED; - - return uf; -} - -/* -translated the UserFlags (userAccountControl) to ACB_CTRL Flags -*/ -uint32 ads_uf2acb(uint32 uf) -{ - uint32 acb = 0x00000000; - - if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED; - if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ; - if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ; - if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS; - if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP; - if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK; - if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY; - if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED; - if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION; - if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH; - if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD; - if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED; - if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED; - - switch (uf & UF_ACCOUNT_TYPE_MASK) - { - case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break; - case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break; - case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break; - case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break; - case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break; - /*Fix Me: what should we do here? */ - default: acb |= ACB_NORMAL;break; - } - - return acb; -} - -/* -get the accountType from the UserFlags -*/ -uint32 ads_uf2atype(uint32 uf) -{ - uint32 atype = 0x00000000; - - if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST; - - return atype; -} - -/* -get the accountType from the groupType -*/ -uint32 ads_gtype2atype(uint32 gtype) -{ - uint32 atype = 0x00000000; - - switch(gtype) { - case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_GLOBAL_GROUP: - atype = ATYPE_SECURITY_GLOBAL_GROUP; - break; - - case GTYPE_DISTRIBUTION_GLOBAL_GROUP: - atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP; - break; - case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP: - atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP; - break; - case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP: - atype = ATYPE_DISTRIBUTION_LOCAL_GROUP; - break; - } - - return atype; -} - -/* turn a sAMAccountType into a SID_NAME_USE */ -enum lsa_SidType ads_atype_map(uint32 atype) -{ - switch (atype & 0xF0000000) { - case ATYPE_GLOBAL_GROUP: - return SID_NAME_DOM_GRP; - case ATYPE_SECURITY_LOCAL_GROUP: - return SID_NAME_ALIAS; - case ATYPE_ACCOUNT: - return SID_NAME_USER; - default: - DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); - } - return SID_NAME_UNKNOWN; -} - const char *ads_get_ldap_server_name(ADS_STRUCT *ads) { return ads->config.ldap_server_name; diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 3e5764a598..102fc83d0f 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -6,17 +6,17 @@ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 Copyright (C) Guenther Deschner 2005 Copyright (C) Gerald Carter 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -198,7 +198,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) if (!server || !*server) { return False; } - + DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", server, ads->server.realm)); @@ -209,7 +209,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) } /* this copes with inet_ntoa brokenness */ - + srv = SMB_STRDUP(server); ZERO_STRUCT( cldap_reply ); @@ -411,7 +411,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) SAFE_FREE(sitename); return NT_STATUS_OK; } - + /* keep track of failures */ add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); } @@ -652,7 +652,7 @@ got_connection: #endif /* If the caller() requested no LDAP bind, then we are done */ - + if (ads->auth.flags & ADS_AUTH_NO_BIND) { status = ADS_SUCCESS; goto out; @@ -663,7 +663,7 @@ got_connection: status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto out; } - + /* Otherwise setup the TCP LDAP session */ ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name, @@ -690,14 +690,14 @@ got_connection: } /* fill in the current time and offsets */ - + status = ads_current_time( ads ); if ( !ADS_ERR_OK(status) ) { goto out; } /* Now do the bind */ - + if (ads->auth.flags & ADS_AUTH_ANON_BIND) { status = ADS_ERROR(ldap_simple_bind_s(ads->ldap.ld, NULL, NULL)); goto out; @@ -781,7 +781,7 @@ static struct berval **ads_dup_values(TALLOC_CTX *ctx, { struct berval **values; int i; - + if (!in_vals) return NULL; for (i=0; in_vals[i]; i++) ; /* count values */ @@ -826,7 +826,7 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals) char **values; int i; size_t converted_size; - + if (!in_vals) return NULL; for (i=0; in_vals[i]; i++) ; /* count values */ @@ -901,7 +901,7 @@ static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, goto done; } } - + /* Paged results only available on ldap v3 or later */ ldap_get_option(ads->ldap.ld, LDAP_OPT_PROTOCOL_VERSION, &version); if (version < LDAP_VERSION3) { @@ -976,7 +976,7 @@ static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, handle them and paged results at the same time. Using them together results in the result record containing the server page control being removed from the result list (tridge/jmcd) - + leaving this in despite the control that says don't generate referrals, in case the server doesn't support it (jmcd) */ @@ -1031,7 +1031,7 @@ done: if (ext_bv) { ber_bvfree(ext_bv); } - + /* if/when we decide to utf8-encode attrs, take out this next line */ TALLOC_FREE(search_attrs); @@ -1159,7 +1159,7 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path, &res, &count, &cookie); if (!ADS_ERR_OK(status)) break; - + ads_process_results(ads, res, fn, data_area); ads_msgfree(ads, res); } @@ -1347,7 +1347,7 @@ char *ads_parent_dn(const char *dn) DEBUG(1, ("asprintf failed!\n")); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } - + status = ads_search(ads, res, expr, attrs); SAFE_FREE(expr); return status; @@ -1362,12 +1362,12 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx) { #define ADS_MODLIST_ALLOC_SIZE 10 LDAPMod **mods; - + if ((mods = TALLOC_ZERO_ARRAY(ctx, LDAPMod *, ADS_MODLIST_ALLOC_SIZE + 1))) /* -1 is safety to make sure we don't go over the end. need to reset it to NULL before doing ldap modify */ mods[ADS_MODLIST_ALLOC_SIZE] = (LDAPMod *) -1; - + return (ADS_MODLIST)mods; } @@ -1408,7 +1408,7 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, modlist[curmod+ADS_MODLIST_ALLOC_SIZE] = (LDAPMod *) -1; *mods = (ADS_MODLIST)modlist; } - + if (!(modlist[curmod] = TALLOC_ZERO_P(ctx, LDAPMod))) return ADS_ERROR(LDAP_NO_MEMORY); modlist[curmod]->mod_type = talloc_strdup(ctx, name); @@ -1541,7 +1541,7 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods) DEBUG(1, ("ads_gen_add: push_utf8_talloc failed!")); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } - + /* find the end of the list, marked by NULL or -1 */ for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++); /* make sure the end of the list is NULL */ @@ -1567,7 +1567,7 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn) DEBUG(1, ("ads_del_dn: push_utf8_talloc failed!")); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } - + ret = ldap_delete_s(ads->ldap.ld, utf8_dn); TALLOC_FREE(utf8_dn); return ADS_ERROR(ret); @@ -1593,7 +1593,7 @@ char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit) /* samba4 might not yet respond to a wellknownobject-query */ return ret ? ret : SMB_STRDUP("cn=Computers"); } - + if (strequal(org_unit, "Computers")) { return SMB_STRDUP("cn=Computers"); } @@ -1668,7 +1668,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid) for (i=1; i < new_ln; i++) { char *s = NULL; - + if (asprintf(&s, "%s,%s", ret, wkn_dn_exp[i]) == -1) { SAFE_FREE(ret); goto out; @@ -1895,7 +1895,7 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n } /* add short name spn */ - + if ( (psp1 = talloc_asprintf(ctx, "%s/%s", spn, machine_name)) == NULL ) { talloc_destroy(ctx); ads_msgfree(ads, res); @@ -1904,13 +1904,13 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n strupper_m(psp1); strlower_m(&psp1[strlen(spn)]); servicePrincipalName[0] = psp1; - + DEBUG(5,("ads_add_service_principal_name: INFO: Adding %s to host %s\n", psp1, machine_name)); /* add fully qualified spn */ - + if ( (psp2 = talloc_asprintf(ctx, "%s/%s", spn, my_fqdn)) == NULL ) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto out; @@ -1926,18 +1926,18 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n ret = ADS_ERROR(LDAP_NO_MEMORY); goto out; } - + ret = ads_add_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName); if (!ADS_ERR_OK(ret)) { DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n")); goto out; } - + if ( (dn_string = ads_get_dn(ads, ctx, res)) == NULL ) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto out; } - + ret = ads_gen_mod(ads, dn_string, mods); if (!ADS_ERR_OK(ret)) { DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n")); @@ -1974,7 +1974,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\ UF_DONT_EXPIRE_PASSWD |\ UF_ACCOUNTDISABLE ); - + if (!(ctx = talloc_init("ads_add_machine_acct"))) return ADS_ERROR(LDAP_NO_MEMORY); @@ -1991,7 +1991,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, if ( !new_dn || !samAccountName ) { goto done; } - + #ifndef ENCTYPE_ARCFOUR_HMAC acct_control |= UF_USE_DES_KEY_ONLY; #endif @@ -2003,7 +2003,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, if (!(mods = ads_init_mods(ctx))) { goto done; } - + ads_mod_str(ctx, &mods, "cn", machine_name); ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName); ads_mod_strlist(ctx, &mods, "objectClass", objectClass); @@ -2015,7 +2015,7 @@ done: SAFE_FREE(machine_escaped); ads_msgfree(ads, res); talloc_destroy(ctx); - + return ret; } @@ -2254,7 +2254,7 @@ static bool ads_dump_field(ADS_STRUCT *ads, char *field, void **values, void *da msg = ads_next_entry(ads, msg)) { char *utf8_field; BerElement *b; - + for (utf8_field=ldap_first_attribute(ads->ldap.ld, (LDAPMessage *)msg,&b); utf8_field; @@ -2373,7 +2373,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) values = ldap_get_values(ads->ldap.ld, msg, field); if (!values) return NULL; - + if (values[0] && pull_utf8_talloc(mem_ctx, &ux_string, values[0], &converted_size)) { @@ -2455,7 +2455,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) size_t num_new_strings; unsigned long int range_start; unsigned long int range_end; - + /* we might have been given the whole lot anyway */ if ((strings = ads_pull_strings(ads, mem_ctx, msg, field, num_strings))) { *more_strings = False; @@ -2481,7 +2481,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) *more_strings = False; return NULL; } - + if (sscanf(&range_attr[strlen(expected_range_attrib)], "%lu-%lu", &range_start, &range_end) == 2) { *more_strings = True; @@ -2508,7 +2508,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) } new_strings = ads_pull_strings(ads, mem_ctx, msg, range_attr, &num_new_strings); - + if (*more_strings && ((*num_strings + num_new_strings) != (range_end + 1))) { DEBUG(1, ("ads_pull_strings_range: Range attribute (%s) tells us we have %lu " "strings in this bunch, but we only got %lu - aborting range retreival\n", @@ -2521,13 +2521,13 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) strings = TALLOC_REALLOC_ARRAY(mem_ctx, current_strings, char *, *num_strings + num_new_strings); - + if (strings == NULL) { ldap_memfree(range_attr); *more_strings = False; return NULL; } - + if (new_strings && num_new_strings) { memcpy(&strings[*num_strings], new_strings, sizeof(*new_strings) * num_new_strings); @@ -2540,7 +2540,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) "%s;range=%d-*", field, (int)*num_strings); - + if (!*next_attribute) { DEBUG(1, ("talloc_asprintf for next attribute failed!\n")); ldap_memfree(range_attr); @@ -2595,7 +2595,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) values = ldap_get_values(ads->ldap.ld, msg, "objectGUID"); if (!values) return False; - + if (values[0]) { memcpy(&flat_guid.info, values[0], sizeof(UUID_FLAT)); smb_uuid_unpack(flat_guid, guid); @@ -2665,7 +2665,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) count++; } } - + ldap_value_free_len(values); return count; } @@ -2700,7 +2700,7 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) ret = false; } } - + ldap_value_free_len(values); return ret; } @@ -2829,7 +2829,7 @@ ADS_STATUS ads_current_time(ADS_STRUCT *ads) } /* but save the time and offset in the original ADS_STRUCT */ - + ads->config.current_time = ads_parse_time(timestr); if (ads->config.current_time != 0) { @@ -2860,7 +2860,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val) ADS_STATUS status; LDAPMessage *res; ADS_STRUCT *ads_s = ads; - + *val = DS_DOMAIN_FUNCTION_2000; /* establish a new ldap tcp session if necessary */ @@ -2880,7 +2880,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val) /* If the attribute does not exist assume it is a Windows 2000 functional domain */ - + status = ads_do_search(ads_s, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(status)) { if ( status.err.rc == LDAP_NO_SUCH_ATTRIBUTE ) { @@ -2894,7 +2894,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val) } DEBUG(3,("ads_domain_func_level: %d\n", *val)); - + ads_msgfree(ads, res); done: @@ -2926,7 +2926,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid) return ADS_ERROR_SYSTEM(ENOENT); } ads_msgfree(ads, res); - + return ADS_SUCCESS; } @@ -3301,26 +3301,26 @@ char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine ADS_STATUS status; int count = 0; char *name = NULL; - + status = ads_find_machine_acct(ads, &res, global_myname()); if (!ADS_ERR_OK(status)) { DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n", global_myname())); goto out; } - + if ( (count = ads_count_replies(ads, res)) != 1 ) { DEBUG(1,("ads_get_dnshostname: %d entries returned!\n", count)); goto out; } - + if ( (name = ads_pull_string(ads, ctx, res, "dNSHostName")) == NULL ) { DEBUG(0,("ads_get_dnshostname: No dNSHostName attribute!\n")); } out: ads_msgfree(ads, res); - + return name; } @@ -3365,26 +3365,26 @@ char* ads_get_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *mach ADS_STATUS status; int count = 0; char *name = NULL; - + status = ads_find_machine_acct(ads, &res, global_myname()); if (!ADS_ERR_OK(status)) { DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n", global_myname())); goto out; } - + if ( (count = ads_count_replies(ads, res)) != 1 ) { DEBUG(1,("ads_get_dnshostname: %d entries returned!\n", count)); goto out; } - + if ( (name = ads_pull_string(ads, ctx, res, "sAMAccountName")) == NULL ) { DEBUG(0,("ads_get_dnshostname: No sAMAccountName attribute!\n")); } out: ads_msgfree(ads, res); - + return name; } @@ -3700,7 +3700,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads, status = ads_do_search_all(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, filter, attrs, &res); - + if (!ADS_ERR_OK(status)) { goto out; } @@ -3828,7 +3828,6 @@ const char *ads_get_extended_right_name_by_guid(ADS_STRUCT *ads, done: ads_msgfree(ads, res); return result; - } /** diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 187fcdf625..693d97626f 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -453,7 +453,6 @@ NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname, return status; } - /**************************************************************************** Hard link a file (UNIX extensions). ****************************************************************************/ @@ -624,222 +623,570 @@ static mode_t unix_filetype_from_wire(uint32_t wire_type) Do a POSIX getfacl (UNIX extensions). ****************************************************************************/ -bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf) +struct getfacl_state { + uint16_t setup; + uint8_t *param; + uint32_t num_data; + uint8_t *data; +}; + +static void cli_posix_getfacl_done(struct tevent_req *subreq) { - unsigned int param_len = 0; - unsigned int data_len = 0; - uint16_t setup = TRANSACT2_QPATHINFO; - char *param; - size_t nlen = 2*(strlen(name)+1); - char *rparam=NULL, *rdata=NULL; - char *p; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct getfacl_state *state = tevent_req_data(req, struct getfacl_state); + NTSTATUS status; - param = SMB_MALLOC_ARRAY(char, 6+nlen+2); - if (!param) { - return false; + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, + &state->data, &state->num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } + tevent_req_done(req); +} - p = param; - memset(p, '\0', 6); - SSVAL(p, 0, SMB_QUERY_POSIX_ACL); - p += 6; - p += clistr_push(cli, p, name, nlen, STR_TERMINATE); - param_len = PTR_DIFF(p, param); +struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct link_state *state = NULL; - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - NULL, 0, cli->max_xmit /* data, length, max */ - )) { - SAFE_FREE(param); - return false; + req = tevent_req_create(mem_ctx, &state, struct getfacl_state); + if (req == NULL) { + return NULL; } - SAFE_FREE(param); + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - return false; + /* Setup param array. */ + state->param = talloc_array(state, uint8_t, 6); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } + memset(state->param, '\0', 6); + SSVAL(state->param, 0, SMB_QUERY_POSIX_ACL); - if (data_len < 6) { - SAFE_FREE(rdata); - SAFE_FREE(rparam); - return false; + state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); + + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } - SAFE_FREE(rparam); - *retbuf = rdata; - *prb_size = (size_t)data_len; + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + talloc_get_size(state->param), /* num param. */ + 2, /* max returned param. */ + NULL, /* data. */ + 0, /* num data. */ + cli->max_xmit); /* max returned data. */ - return true; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_posix_getfacl_done, req); + return req; +} + +NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + size_t *prb_size, + char **retbuf) +{ + struct getfacl_state *state = tevent_req_data(req, struct getfacl_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *prb_size = (size_t)state->num_data; + *retbuf = (char *)talloc_move(mem_ctx, &state->data); + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_getfacl(struct cli_state *cli, + const char *fname, + TALLOC_CTX *mem_ctx, + size_t *prb_size, + char **retbuf) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_getfacl_send(frame, + ev, + cli, + fname); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** Stat a file (UNIX extensions). ****************************************************************************/ -bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf) +struct stat_state { + uint16_t setup; + uint8_t *param; + uint32_t num_data; + uint8_t *data; +}; + +static void cli_posix_stat_done(struct tevent_req *subreq) { - unsigned int param_len = 0; - unsigned int data_len = 0; - uint16_t setup = TRANSACT2_QPATHINFO; - char *param; - size_t nlen = 2*(strlen(name)+1); - char *rparam=NULL, *rdata=NULL; - char *p; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct stat_state *state = tevent_req_data(req, struct stat_state); + NTSTATUS status; - ZERO_STRUCTP(sbuf); + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, + &state->data, &state->num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} - param = SMB_MALLOC_ARRAY(char, 6+nlen+2); - if (!param) { - return false; +struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct stat_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct stat_state); + if (req == NULL) { + return NULL; } - p = param; - memset(p, '\0', 6); - SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC); - p += 6; - p += clistr_push(cli, p, name, nlen, STR_TERMINATE); - param_len = PTR_DIFF(p, param); - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - NULL, 0, cli->max_xmit /* data, length, max */ - )) { - SAFE_FREE(param); - return false; + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); + + /* Setup param array. */ + state->param = talloc_array(state, uint8_t, 6); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } + memset(state->param, '\0', 6); + SSVAL(state->param, 0, SMB_QUERY_FILE_UNIX_BASIC); - SAFE_FREE(param); + state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - return false; + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } - if (data_len < 96) { - SAFE_FREE(rdata); - SAFE_FREE(rparam); - return false; + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + talloc_get_size(state->param), /* num param. */ + 2, /* max returned param. */ + NULL, /* data. */ + 0, /* num data. */ + 96); /* max returned data. */ + + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_posix_stat_done, req); + return req; +} + +NTSTATUS cli_posix_stat_recv(struct tevent_req *req, + SMB_STRUCT_STAT *sbuf) +{ + struct stat_state *state = tevent_req_data(req, struct stat_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + + if (state->num_data != 96) { + return NT_STATUS_DATA_ERROR; } - sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */ - sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */ + sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0); /* total size, in bytes */ + sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8); /* number of blocks allocated */ #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE; #else /* assume 512 byte blocks */ sbuf->st_ex_blocks /= 512; #endif - sbuf->st_ex_ctime = interpret_long_date(rdata + 16); /* time of last change */ - sbuf->st_ex_atime = interpret_long_date(rdata + 24); /* time of last access */ - sbuf->st_ex_mtime = interpret_long_date(rdata + 32); /* time of last modification */ + sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16)); /* time of last change */ + sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24)); /* time of last access */ + sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32)); /* time of last modification */ - sbuf->st_ex_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */ - sbuf->st_ex_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */ - sbuf->st_ex_mode |= unix_filetype_from_wire(IVAL(rdata, 56)); + sbuf->st_ex_uid = (uid_t) IVAL(state->data,40); /* user ID of owner */ + sbuf->st_ex_gid = (gid_t) IVAL(state->data,48); /* group ID of owner */ + sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56)); #if defined(HAVE_MAKEDEV) { - uint32_t dev_major = IVAL(rdata,60); - uint32_t dev_minor = IVAL(rdata,68); + uint32_t dev_major = IVAL(state->data,60); + uint32_t dev_minor = IVAL(state->data,68); sbuf->st_ex_rdev = makedev(dev_major, dev_minor); } #endif - sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */ - sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */ - sbuf->st_ex_nlink = IVAL(rdata,92); /* number of hard links */ + sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76); /* inode */ + sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84)); /* protection */ + sbuf->st_ex_nlink = IVAL(state->data,92); /* number of hard links */ - SAFE_FREE(rdata); - SAFE_FREE(rparam); + return NT_STATUS_OK; +} - return true; +NTSTATUS cli_posix_stat(struct cli_state *cli, + const char *fname, + SMB_STRUCT_STAT *sbuf) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_stat_send(frame, + ev, + cli, + fname); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_stat_recv(req, sbuf); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } + /**************************************************************************** Chmod or chown a file internal (UNIX extensions). ****************************************************************************/ -static bool cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32_t mode, uint32_t uid, uint32_t gid) +struct ch_state { + uint16_t setup; + uint8_t *param; + uint8_t *data; +}; + +static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq) { - unsigned int data_len = 0; - unsigned int param_len = 0; - uint16_t setup = TRANSACT2_SETPATHINFO; - size_t nlen = 2*(strlen(fname)+1); - char *param; - char data[100]; - char *rparam=NULL, *rdata=NULL; - char *p; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct ch_state *state = tevent_req_data(req, struct ch_state); + NTSTATUS status; - param = SMB_MALLOC_ARRAY(char, 6+nlen+2); - if (!param) { - return false; + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } - memset(param, '\0', 6); - memset(data, 0, sizeof(data)); + tevent_req_done(req); +} - SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC); - p = ¶m[6]; +static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t mode, + uint32_t uid, + uint32_t gid) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct ch_state *state = NULL; - p += clistr_push(cli, p, fname, nlen, STR_TERMINATE); - param_len = PTR_DIFF(p, param); + req = tevent_req_create(mem_ctx, &state, struct ch_state); + if (req == NULL) { + return NULL; + } - memset(data, 0xff, 40); /* Set all sizes/times to no change. */ + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); - SIVAL(data,40,uid); - SIVAL(data,48,gid); - SIVAL(data,84,mode); + /* Setup param array. */ + state->param = talloc_array(state, uint8_t, 6); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); + } + memset(state->param, '\0', 6); + SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC); - data_len = 100; + state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - (char *)&data, data_len, cli->max_xmit /* data, length, max */ - )) { - SAFE_FREE(param); - return False; + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } - SAFE_FREE(param); - - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - return false; + /* Setup data array. */ + state->data = talloc_array(state, uint8_t, 100); + if (tevent_req_nomem(state->data, req)) { + return tevent_req_post(req, ev); } + memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */ + memset(&state->data[40], '\0', 60); + SIVAL(state->data,40,uid); + SIVAL(state->data,48,gid); + SIVAL(state->data,84,mode); - SAFE_FREE(rdata); - SAFE_FREE(rparam); + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + talloc_get_size(state->param), /* num param. */ + 2, /* max returned param. */ + state->data, /* data. */ + talloc_get_size(state->data), /* num data. */ + 0); /* max returned data. */ - return true; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req); + return req; } /**************************************************************************** chmod a file (UNIX extensions). ****************************************************************************/ -bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode) +struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + mode_t mode) +{ + return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli, + fname, + unix_perms_to_wire(mode), + SMB_UID_NO_CHANGE, + SMB_GID_NO_CHANGE); +} + +NTSTATUS cli_posix_chmod_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode) { - return cli_unix_chmod_chown_internal(cli, fname, - unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE); + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_chmod_send(frame, + ev, + cli, + fname, + mode); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_chmod_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** chown a file (UNIX extensions). ****************************************************************************/ -bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid) +struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uid_t uid, + gid_t gid) +{ + return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli, + fname, + SMB_MODE_NO_CHANGE, + (uint32_t)uid, + (uint32_t)gid); +} + +NTSTATUS cli_posix_chown_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_chown(struct cli_state *cli, + const char *fname, + uid_t uid, + gid_t gid) { - return cli_unix_chmod_chown_internal(cli, fname, - SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid); + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_chown_send(frame, + ev, + cli, + fname, + uid, + gid); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_chown_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -1506,6 +1853,135 @@ NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname) Set or clear the delete on close flag. ****************************************************************************/ +struct doc_state { + uint16_t setup; + uint8_t param[6]; + uint8_t data[1]; +}; + +static void cli_nt_delete_on_close_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct doc_state *state = tevent_req_data(req, struct doc_state); + NTSTATUS status; + + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} + +struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + bool flag) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct doc_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct doc_state); + if (req == NULL) { + return NULL; + } + + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); + + /* Setup param array. */ + memset(state->param, '\0', 6); + SSVAL(state->param,0,fnum); + SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO); + + /* Setup data array. */ + SCVAL(&state->data[0], 0, flag ? 1 : 0); + + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + 6, /* num param. */ + 2, /* max returned param. */ + state->data, /* data. */ + 1, /* num data. */ + 0); /* max returned data. */ + + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req); + return req; +} + +NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} + +NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_nt_delete_on_close_send(frame, + ev, + cli, + fnum, + flag); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_nt_delete_on_close_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; +} + +#if 0 int cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag) { unsigned int data_len = 1; @@ -1542,6 +2018,7 @@ int cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag) return true; } +#endif struct cli_ntcreate_state { uint16_t vwv[24]; diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 5606b8e7c9..fb87b4dc9a 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -626,8 +626,8 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx, struct ip_service_name *r = &dclist[count]; - r->port = dcs[count].port; - r->hostname = dcs[count].hostname; + r->port = dcs[i].port; + r->hostname = dcs[i].hostname; /* If we don't have an IP list for a name, lookup it up */ diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index bacd907512..98885876b3 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -120,7 +120,7 @@ SMBC_module_init(void * punused) } -void +static void SMBC_module_terminate(void) { gencache_shutdown(); diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h index 9d63021f42..70f90b5cd5 100644 --- a/source3/modules/onefs.h +++ b/source3/modules/onefs.h @@ -170,4 +170,17 @@ ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd, ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset, size_t count); +void init_stat_ex_from_onefs_stat(struct stat_ex *dst, const struct stat *src); + +int onefs_sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf); + +int onefs_sys_fstat(int fd, SMB_STRUCT_STAT *sbuf); + +int onefs_sys_fstat_at(int base_fd, const char *fname, SMB_STRUCT_STAT *sbuf, + int flags); + +int onefs_sys_lstat(const char *fname, SMB_STRUCT_STAT *sbuf); + + + #endif /* _ONEFS_H */ diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c index d66e5d65fa..81bdfd26cc 100644 --- a/source3/modules/onefs_acl.c +++ b/source3/modules/onefs_acl.c @@ -393,7 +393,7 @@ onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd) if (error) return false; - if ((sbuf.st_flags & SF_HASNTFSACL) != 0) { + if ((sbuf.st_ex_flags & SF_HASNTFSACL) != 0) { DEBUG(10, ("Did not canonicalize ACLs because a " "Windows ACL set was found for file %s\n", fsp->fsp_name)); @@ -540,7 +540,8 @@ static bool add_sfs_aces(files_struct *fsp, struct ifs_security_descriptor *sd) } /* Only continue if this is a synthetic ACL and a directory. */ - if (S_ISDIR(sbuf.st_mode) && (sbuf.st_flags & SF_HASNTFSACL) == 0) { + if (S_ISDIR(sbuf.st_ex_mode) && + (sbuf.st_ex_flags & SF_HASNTFSACL) == 0) { struct ifs_ace new_aces[6]; struct ifs_ace *old_aces; int i, num_aces_to_add = 0; diff --git a/source3/modules/onefs_dir.c b/source3/modules/onefs_dir.c index 47da33fff1..2ab8b86771 100644 --- a/source3/modules/onefs_dir.c +++ b/source3/modules/onefs_dir.c @@ -43,7 +43,7 @@ #define RDP_DIRENTRIES_SIZE ((size_t)(RDP_BATCH_SIZE * sizeof(struct dirent))) static char *rdp_direntries = NULL; -static SMB_STRUCT_STAT *rdp_stats = NULL; +static struct stat *rdp_stats = NULL; static uint64_t *rdp_cookies = NULL; struct rdp_dir_state { @@ -113,7 +113,7 @@ rdp_init(struct rdp_dir_state *dsp) if (!rdp_stats) { rdp_stats = - SMB_MALLOC(RDP_BATCH_SIZE * sizeof(SMB_STRUCT_STAT)); + SMB_MALLOC(RDP_BATCH_SIZE * sizeof(struct stat)); if (!rdp_stats) return ENOMEM; } @@ -367,11 +367,15 @@ onefs_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, /* Return an entry from cache */ ret_direntp = ((SMB_STRUCT_DIRENT *)dsp->direntries_cursor); if (sbuf) { - *sbuf = rdp_stats[dsp->stat_cursor]; + struct stat onefs_sbuf; + + onefs_sbuf = rdp_stats[dsp->stat_cursor]; + init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf); + /* readdirplus() sets st_ino field to 0, if it was * unable to retrieve stat information for that * particular directory entry. */ - if (sbuf->st_ino == 0) + if (sbuf->st_ex_ino == 0) SET_STAT_INVALID(*sbuf); } diff --git a/source3/modules/onefs_notify.c b/source3/modules/onefs_notify.c index 3455afd4ab..0447d0c03e 100644 --- a/source3/modules/onefs_notify.c +++ b/source3/modules/onefs_notify.c @@ -630,21 +630,21 @@ onefs_notify_watch(vfs_handle_struct *vfs_handle, } /* Get LIN for directory */ - if (sys_fstat(e->dir_fd, &sbuf)) { + if (onefs_sys_fstat(e->dir_fd, &sbuf)) { DEBUG(0, ("stat on directory fd failed: %s\n", strerror(errno))); status = map_nt_error_from_unix(errno); goto err; } - if (sbuf.st_ino == 0) { + if (sbuf.st_ex_ino == 0) { DEBUG(0, ("0 LIN found!\n")); goto err; } wc->ctx = ctx; wc->watch_fd = e->dir_fd; - wc->watch_lin = sbuf.st_ino; + wc->watch_lin = sbuf.st_ex_ino; wc->ifs_event_fd = ifs_event_fd; wc->ifs_filter = ifs_filter; wc->smb_filter = smb_filter; @@ -669,7 +669,7 @@ onefs_notify_watch(vfs_handle_struct *vfs_handle, "ifs_filter=0x%x, watch_tree=%d, ifs_event_fd=%d, " "dir_fd=%d, dir_lin=0x%llx\n", e->path, smb_filter, ifs_filter, watch_tree, - ifs_event_fd, e->dir_fd, sbuf.st_ino)); + ifs_event_fd, e->dir_fd, sbuf.st_ex_ino)); return NT_STATUS_OK; diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index 6cfa24f9f6..21c5d51f90 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -148,7 +148,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * open flags. JRA. */ - if (file_existed && S_ISFIFO(psbuf->st_mode)) { + if (file_existed && S_ISFIFO(psbuf->st_ex_mode)) { local_flags |= O_NONBLOCK; } #endif @@ -289,13 +289,13 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * so catch a directory open and return an EISDIR. JRA. */ - if(S_ISDIR(psbuf->st_mode)) { + if(S_ISDIR(psbuf->st_ex_mode)) { fd_close(fsp); errno = EISDIR; return NT_STATUS_FILE_IS_A_DIRECTORY; } - fsp->mode = psbuf->st_mode; + fsp->mode = psbuf->st_ex_mode; fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; @@ -661,7 +661,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, "FILE_CREATE requested for file %s " "and file already exists.\n", fname)); - if (S_ISDIR(psbuf->st_mode)) { + if (S_ISDIR(psbuf->st_ex_mode)) { errno = EISDIR; } else { errno = EEXIST; @@ -687,13 +687,13 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, (create_disposition == FILE_OVERWRITE_IF))) { if (!open_match_attributes(conn, fname, existing_dos_attributes, - new_dos_attributes, psbuf->st_mode, + new_dos_attributes, psbuf->st_ex_mode, unx_mode, &new_unx_mode)) { DEBUG(5, ("onefs_open_file_ntcreate: attributes " "missmatch for file %s (%x %x) (0%o, 0%o)\n", fname, existing_dos_attributes, new_dos_attributes, - (unsigned int)psbuf->st_mode, + (unsigned int)psbuf->st_ex_mode, (unsigned int)unx_mode )); errno = EACCES; return NT_STATUS_ACCESS_DENIED; @@ -816,7 +816,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } if (file_existed) { - struct timespec old_write_time = get_mtimespec(psbuf); + struct timespec old_write_time = psbuf->st_ex_mtime; id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(talloc_tos(), id, @@ -900,7 +900,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, struct deferred_open_record state; struct timespec old_write_time; - old_write_time = get_mtimespec(psbuf); + old_write_time = psbuf->st_ex_mtime; DEBUG(3, ("Someone created file %s with an " "oplock after we looked: Retrying\n", @@ -1089,7 +1089,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } if (!file_existed) { - struct timespec old_write_time = get_mtimespec(psbuf); + struct timespec old_write_time = psbuf->st_ex_mtime; /* * Deal with the race condition where two smbd's detect the * file doesn't exist and do the create at the same time. One @@ -1267,7 +1267,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * May be necessary depending on acl policies. */ if (!posix_open && !file_existed && !def_acl && !(VALID_STAT(*psbuf) - && (psbuf->st_flags & SF_HASNTFSACL))) { + && (psbuf->st_ex_flags & SF_HASNTFSACL))) { int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ @@ -1495,7 +1495,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, return map_nt_error_from_unix(errno); } - if (!S_ISDIR(psbuf->st_mode)) { + if (!S_ISDIR(psbuf->st_ex_mode)) { DEBUG(0, ("Directory just '%s' created is not a " "directory\n", fname)); return NT_STATUS_ACCESS_DENIED; @@ -1509,9 +1509,9 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, * parent dir. */ if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - (mode & ~psbuf->st_mode)) { - SMB_VFS_CHMOD(conn, fname, (psbuf->st_mode | - (mode & ~psbuf->st_mode))); + (mode & ~psbuf->st_ex_mode)) { + SMB_VFS_CHMOD(conn, fname, (psbuf->st_ex_mode | + (mode & ~psbuf->st_ex_mode))); } } @@ -1533,7 +1533,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, } /* Setup the files_struct for it. */ - fsp->mode = psbuf->st_mode; + fsp->mode = psbuf->st_ex_mode; fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; @@ -1556,7 +1556,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - mtimespec = get_mtimespec(psbuf); + mtimespec = psbuf->st_ex_mtime; /* * Still set the samba share mode lock for correct delete-on-close @@ -1904,7 +1904,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, } } - if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + if (!fsp->is_directory && S_ISDIR(sbuf.st_ex_mode)) { status = NT_STATUS_ACCESS_DENIED; goto fail; } @@ -1912,7 +1912,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { if (allocation_size - && (allocation_size > sbuf.st_size)) { + && (allocation_size > sbuf.st_ex_size)) { fsp->initial_allocation_size = smb_roundup( fsp->conn, allocation_size); if (fsp->is_directory) { @@ -1927,7 +1927,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, } } else { fsp->initial_allocation_size = smb_roundup( - fsp->conn, (uint64_t)sbuf.st_size); + fsp->conn, (uint64_t)sbuf.st_ex_size); } } diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index 05b36d7d3c..284e199fc5 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -222,81 +222,84 @@ static void merge_stat(SMB_STRUCT_STAT *stream_sbuf, { int dos_flags = (UF_DOS_NOINDEX | UF_DOS_ARCHIVE | UF_DOS_HIDDEN | UF_DOS_RO | UF_DOS_SYSTEM); - stream_sbuf->st_mtime = base_sbuf->st_mtime; - stream_sbuf->st_ctime = base_sbuf->st_ctime; - stream_sbuf->st_atime = base_sbuf->st_atime; - stream_sbuf->st_flags &= ~dos_flags; - stream_sbuf->st_flags |= base_sbuf->st_flags & dos_flags; + stream_sbuf->st_ex_mtime = base_sbuf->st_ex_mtime; + stream_sbuf->st_ex_ctime = base_sbuf->st_ex_ctime; + stream_sbuf->st_ex_atime = base_sbuf->st_ex_atime; + stream_sbuf->st_ex_flags &= ~dos_flags; + stream_sbuf->st_ex_flags |= base_sbuf->st_ex_flags & dos_flags; } /* fake timestamps */ -static void onefs_adjust_stat_time(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) +static void onefs_adjust_stat_time(struct connection_struct *conn, + const char *fname, SMB_STRUCT_STAT *sbuf) { struct onefs_vfs_share_config cfg; struct timeval tv_now = {0, 0}; bool static_mtime = False; bool static_atime = False; - if (!onefs_get_config(SNUM(handle->conn), + if (!onefs_get_config(SNUM(conn), ONEFS_VFS_CONFIG_FAKETIMESTAMPS, &cfg)) { return; } - if (IS_MTIME_STATIC_PATH(handle->conn, &cfg, fname)) { - sbuf->st_mtime = sbuf->st_birthtime; + if (IS_MTIME_STATIC_PATH(conn, &cfg, fname)) { + sbuf->st_ex_mtime = sbuf->st_ex_btime; static_mtime = True; } - if (IS_ATIME_STATIC_PATH(handle->conn, &cfg, fname)) { - sbuf->st_atime = sbuf->st_birthtime; + if (IS_ATIME_STATIC_PATH(conn, &cfg, fname)) { + sbuf->st_ex_atime = sbuf->st_ex_btime; static_atime = True; } - if (IS_CTIME_NOW_PATH(handle->conn, &cfg, fname)) { + if (IS_CTIME_NOW_PATH(conn, &cfg, fname)) { if (cfg.ctime_slop < 0) { - sbuf->st_birthtime = INT_MAX - 1; + sbuf->st_ex_btime.tv_sec = INT_MAX - 1; } else { GetTimeOfDay(&tv_now); - sbuf->st_birthtime = tv_now.tv_sec + cfg.ctime_slop; + sbuf->st_ex_btime.tv_sec = tv_now.tv_sec + + cfg.ctime_slop; } } - if (!static_mtime && IS_MTIME_NOW_PATH(handle->conn,&cfg,fname)) { + if (!static_mtime && IS_MTIME_NOW_PATH(conn,&cfg,fname)) { if (cfg.mtime_slop < 0) { - sbuf->st_mtime = INT_MAX - 1; + sbuf->st_ex_mtime.tv_sec = INT_MAX - 1; } else { if (tv_now.tv_sec == 0) GetTimeOfDay(&tv_now); - sbuf->st_mtime = tv_now.tv_sec + cfg.mtime_slop; + sbuf->st_ex_mtime.tv_sec = tv_now.tv_sec + + cfg.mtime_slop; } } - if (!static_atime && IS_ATIME_NOW_PATH(handle->conn,&cfg,fname)) { + if (!static_atime && IS_ATIME_NOW_PATH(conn,&cfg,fname)) { if (cfg.atime_slop < 0) { - sbuf->st_atime = INT_MAX - 1; + sbuf->st_ex_atime.tv_sec = INT_MAX - 1; } else { if (tv_now.tv_sec == 0) GetTimeOfDay(&tv_now); - sbuf->st_atime = tv_now.tv_sec + cfg.atime_slop; + sbuf->st_ex_atime.tv_sec = tv_now.tv_sec + + cfg.atime_slop; } } } -static int stat_stream(vfs_handle_struct *handle, const char *base, +static int stat_stream(struct connection_struct *conn, const char *base, const char *stream, SMB_STRUCT_STAT *sbuf, int flags) { SMB_STRUCT_STAT base_sbuf; int base_fd = -1, dir_fd, ret, saved_errno; - dir_fd = get_stream_dir_fd(handle->conn, base, &base_fd); + dir_fd = get_stream_dir_fd(conn, base, &base_fd); if (dir_fd < 0) { return -1; } /* Stat the stream. */ - ret = enc_fstatat(dir_fd, stream, ENC_DEFAULT, sbuf, flags); + ret = onefs_sys_fstat_at(dir_fd, stream, sbuf, flags); if (ret != -1) { /* Now stat the base file and merge the results. */ - ret = sys_fstat(base_fd, &base_sbuf); + ret = onefs_sys_fstat(base_fd, &base_sbuf); if (ret != -1) { merge_stat(sbuf, &base_sbuf); } @@ -322,15 +325,15 @@ int onefs_stat(vfs_handle_struct *handle, const char *path, return ret; if (!is_stream) { - ret = SMB_VFS_NEXT_STAT(handle, path, sbuf); + ret = onefs_sys_stat(path, sbuf); } else if (!stream) { /* If it's the ::$DATA stream just stat the base file name. */ - ret = SMB_VFS_NEXT_STAT(handle, base, sbuf); + ret = onefs_sys_stat(base, sbuf); } else { - ret = stat_stream(handle, base, stream, sbuf, 0); + ret = stat_stream(handle->conn, base, stream, sbuf, 0); } - onefs_adjust_stat_time(handle, path, sbuf); + onefs_adjust_stat_time(handle->conn, path, sbuf); return ret; } @@ -341,20 +344,20 @@ int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp, int ret; /* Stat the stream, by calling next_fstat on the stream's fd. */ - ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); + ret = onefs_sys_fstat(fsp->fh->fd, sbuf); if (ret == -1) { return ret; } /* Stat the base file and merge the results. */ if (fsp != NULL && fsp->base_fsp != NULL) { - ret = sys_fstat(fsp->base_fsp->fh->fd, &base_sbuf); + ret = onefs_sys_fstat(fsp->base_fsp->fh->fd, &base_sbuf); if (ret != -1) { merge_stat(sbuf, &base_sbuf); } } - onefs_adjust_stat_time(handle, fsp->fsp_name, sbuf); + onefs_adjust_stat_time(handle->conn, fsp->fsp_name, sbuf); return ret; } @@ -371,16 +374,16 @@ int onefs_lstat(vfs_handle_struct *handle, const char *path, return ret; if (!is_stream) { - ret = SMB_VFS_NEXT_LSTAT(handle, path, sbuf); + ret = onefs_sys_lstat(path, sbuf); } else if (!stream) { /* If it's the ::$DATA stream just stat the base file name. */ - ret = SMB_VFS_NEXT_LSTAT(handle, base, sbuf); + ret = onefs_sys_lstat(base, sbuf); } else { - ret = stat_stream(handle, base, stream, sbuf, + ret = stat_stream(handle->conn, base, stream, sbuf, AT_SYMLINK_NOFOLLOW); } - onefs_adjust_stat_time(handle, path, sbuf); + onefs_adjust_stat_time(handle->conn, path, sbuf); return ret; } @@ -614,7 +617,7 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp, if (!add_one_stream(state->mem_ctx, &state->num_streams, &state->streams, - dp->d_name, stream_sbuf.st_size, + dp->d_name, stream_sbuf.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &stream_sbuf))) { state->status = NT_STATUS_NO_MEMORY; @@ -677,10 +680,10 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, } /* Add the default stream. */ - if (S_ISREG(sbuf.st_mode)) { + if (S_ISREG(sbuf.st_ex_mode)) { if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, - "", sbuf.st_size, + "", sbuf.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf))) { return NT_STATUS_NO_MEMORY; @@ -692,7 +695,7 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, state.status = NT_STATUS_OK; /* If there are more streams, add them too. */ - if (sbuf.st_flags & UF_HASADS) { + if (sbuf.st_ex_flags & UF_HASADS) { status = walk_onefs_streams(handle->conn, fsp, fname, &state, &sbuf); diff --git a/source3/modules/onefs_system.c b/source3/modules/onefs_system.c index 3e51c6cd85..d2f853f9ee 100644 --- a/source3/modules/onefs_system.c +++ b/source3/modules/onefs_system.c @@ -666,3 +666,97 @@ out: return ret; } + +void init_stat_ex_from_onefs_stat(struct stat_ex *dst, const struct stat *src) +{ + ZERO_STRUCT(*dst); + + dst->st_ex_dev = src->st_dev; + dst->st_ex_ino = src->st_ino; + dst->st_ex_mode = src->st_mode; + dst->st_ex_nlink = src->st_nlink; + dst->st_ex_uid = src->st_uid; + dst->st_ex_gid = src->st_gid; + dst->st_ex_rdev = src->st_rdev; + dst->st_ex_size = src->st_size; + dst->st_ex_atime = src->st_atimespec; + dst->st_ex_mtime = src->st_mtimespec; + dst->st_ex_ctime = src->st_ctimespec; + dst->st_ex_btime = src->st_birthtimespec; + dst->st_ex_blksize = src->st_blksize; + dst->st_ex_blocks = src->st_blocks; + + dst->st_ex_flags = src->st_flags; + + dst->vfs_private = src->st_snapid; +} + +int onefs_sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf) +{ + int ret; + struct stat onefs_sbuf; + + ret = stat(fname, &onefs_sbuf); + + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(onefs_sbuf.st_mode)) { + onefs_sbuf.st_size = 0; + } + init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf); + } + return ret; +} + +int onefs_sys_fstat(int fd, SMB_STRUCT_STAT *sbuf) +{ + int ret; + struct stat onefs_sbuf; + + ret = fstat(fd, &onefs_sbuf); + + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(onefs_sbuf.st_mode)) { + onefs_sbuf.st_size = 0; + } + init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf); + } + return ret; +} + +int onefs_sys_fstat_at(int base_fd, const char *fname, SMB_STRUCT_STAT *sbuf, + int flags) +{ + int ret; + struct stat onefs_sbuf; + + ret = enc_fstatat(base_fd, fname, ENC_DEFAULT, &onefs_sbuf, flags); + + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(onefs_sbuf.st_mode)) { + onefs_sbuf.st_size = 0; + } + init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf); + } + return ret; +} + +int onefs_sys_lstat(const char *fname, SMB_STRUCT_STAT *sbuf) +{ + int ret; + struct stat onefs_sbuf; + + ret = lstat(fname, &onefs_sbuf); + + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(onefs_sbuf.st_mode)) { + onefs_sbuf.st_size = 0; + } + init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf); + } + return ret; +} + diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c index e4a0febbec..7414f16cf9 100644 --- a/source3/modules/vfs_onefs.c +++ b/source3/modules/vfs_onefs.c @@ -88,7 +88,7 @@ static uint64_t onefs_get_alloc_size(struct vfs_handle_struct *handle, START_PROFILE(syscall_get_alloc_size); - if(S_ISDIR(sbuf->st_mode)) { + if(S_ISDIR(sbuf->st_ex_mode)) { result = 0; goto out; } @@ -115,9 +115,9 @@ static struct file_id onefs_file_id_create(struct vfs_handle_struct *handle, * blob */ ZERO_STRUCT(key); - key.devid = sbuf->st_dev; - key.inode = sbuf->st_ino; - key.extid = sbuf->st_snapid; + key.devid = sbuf->st_ex_dev; + key.inode = sbuf->st_ex_ino; + key.extid = sbuf->vfs_private; return key; } @@ -152,7 +152,7 @@ static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path, const char *name, TALLOC_CTX *mem_ctx, char **found_name) { - SMB_STRUCT_STAT sb; + struct stat sb; struct connection_struct *conn = handle->conn; struct stat_extra se; int result; @@ -278,11 +278,11 @@ static vfs_op_tuple onefs_ops[] = { {SMB_VFS_OP(onefs_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(onefs_stat), SMB_VFS_OP_STAT, - SMB_VFS_LAYER_TRANSPARENT}, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(onefs_fstat), SMB_VFS_OP_FSTAT, - SMB_VFS_LAYER_TRANSPARENT}, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(onefs_lstat), SMB_VFS_OP_LSTAT, - SMB_VFS_LAYER_TRANSPARENT}, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(onefs_get_alloc_size), SMB_VFS_OP_GET_ALLOC_SIZE, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(onefs_unlink), SMB_VFS_OP_UNLINK, diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c index 9504e4d53c..0563af383c 100644 --- a/source3/pam_smbpass/pam_smb_passwd.c +++ b/source3/pam_smbpass/pam_smb_passwd.c @@ -45,7 +45,7 @@ #include "support.h" -int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *pass_new ) +static int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *pass_new ) { int retval; char *err_str = NULL; diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c index 855885a6d7..98dda4e8cc 100644 --- a/source3/pam_smbpass/support.c +++ b/source3/pam_smbpass/support.c @@ -21,7 +21,21 @@ #include "support.h" #include "../libcli/auth/libcli_auth.h" +#if defined(HAVE_SECURITY_PAM_EXT_H) +#include <security/pam_ext.h> +#elif defined(HAVE_PAM_PAM_EXT_H) +#include <pam/pam_ext.h> +#endif + +#if defined(HAVE_SECURITY__PAM_MACROS_H) +#include <security/_pam_macros.h> +#elif defined(HAVE_PAM__PAM_MACROS_H) +#include <pam/_pam_macros.h> +#endif +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif #define _pam_overwrite(x) \ do { \ diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 57fdb6e044..7e4371bf0b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -9775,3 +9775,8 @@ const char *lp_socket_address(void) } return Globals.szSocketAddress; } + +void lp_set_passdb_backend(const char *backend) +{ + string_set(&Globals.szPassdbBackend, backend); +} diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 6aab5e377c..51190e0bc2 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -627,7 +627,14 @@ bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid, } /************************************************************* - Change a password entry in the local smbpasswd file. + Change a password entry in the local passdb backend. + + Assumptions: + - always called as root + - ignores the account type except when adding a new account + - will create/delete the unix account if the relative + add/delete user script is configured + *************************************************************/ NTSTATUS local_password_change(const char *user_name, @@ -636,133 +643,135 @@ NTSTATUS local_password_change(const char *user_name, char **pp_err_str, char **pp_msg_str) { - struct samu *sam_pass=NULL; - uint32 other_acb; + TALLOC_CTX *tosctx; + struct samu *sam_pass; + uint32_t acb; + uint32_t rid; NTSTATUS result; + bool user_exists; + int ret = -1; *pp_err_str = NULL; *pp_msg_str = NULL; - /* Get the smb passwd entry for this user */ - - if ( !(sam_pass = samu_new( NULL )) ) { + tosctx = talloc_tos(); + if (!tosctx) { return NT_STATUS_NO_MEMORY; } - become_root(); - if(!pdb_getsampwnam(sam_pass, user_name)) { - unbecome_root(); - TALLOC_FREE(sam_pass); - - if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { - int tmp_debug = DEBUGLEVEL; - struct passwd *pwd; - - /* Might not exist in /etc/passwd. */ - - if (tmp_debug < 1) { - DEBUGLEVEL = 1; - } + sam_pass = samu_new(tosctx); + if (!sam_pass) { + result = NT_STATUS_NO_MEMORY; + goto done; + } - if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), user_name)) ) { - return NT_STATUS_NO_SUCH_USER; + /* Get the smb passwd entry for this user */ + user_exists = pdb_getsampwnam(sam_pass, user_name); + + /* Check delete first, we don't need to do anything else if we + * are going to delete the acocunt */ + if (user_exists && (local_flags & LOCAL_DELETE_USER)) { + + result = pdb_delete_user(tosctx, sam_pass); + if (!NT_STATUS_IS_OK(result)) { + ret = asprintf(pp_err_str, + "Failed to delete entry for user %s.\n", + user_name); + if (ret < 0) { + *pp_err_str = NULL; } - - /* create the struct samu and initialize the basic Unix properties */ - - if ( !(sam_pass = samu_new( NULL )) ) { - return NT_STATUS_NO_MEMORY; + result = NT_STATUS_UNSUCCESSFUL; + } else { + ret = asprintf(pp_msg_str, + "Deleted user %s.\n", + user_name); + if (ret < 0) { + *pp_msg_str = NULL; } + } + goto done; + } - result = samu_set_unix( sam_pass, pwd ); - - DEBUGLEVEL = tmp_debug; + if (user_exists && (local_flags & LOCAL_ADD_USER)) { + /* the entry already existed */ + local_flags &= ~LOCAL_ADD_USER; + } - TALLOC_FREE( pwd ); + if (!user_exists && !(local_flags & LOCAL_ADD_USER)) { + ret = asprintf(pp_err_str, + "Failed to find entry for user %s.\n", + user_name); + if (ret < 0) { + *pp_err_str = NULL; + } + result = NT_STATUS_NO_SUCH_USER; + goto done; + } - if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) { - return result; - } + /* First thing add the new user if we are required to do so */ + if (local_flags & LOCAL_ADD_USER) { - if (!NT_STATUS_IS_OK(result)) { - if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n", - user_name, nt_errstr(result)) < 0) { - *pp_err_str = NULL; - } - return result; - } + if (local_flags & LOCAL_TRUST_ACCOUNT) { + acb = ACB_WSTRUST; + } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { + acb = ACB_DOMTRUST; } else { - if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) { - *pp_err_str = NULL; - } - return NT_STATUS_NO_SUCH_USER; + acb = ACB_NORMAL; } - } else { - unbecome_root(); - /* the entry already existed */ - local_flags &= ~LOCAL_ADD_USER; - } - /* the 'other' acb bits not being changed here */ - other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL))); - if (local_flags & LOCAL_TRUST_ACCOUNT) { - if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) { - if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) { + result = pdb_create_user(tosctx, user_name, acb, &rid); + if (!NT_STATUS_IS_OK(result)) { + ret = asprintf(pp_err_str, + "Failed to add entry for user %s.\n", + user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { - if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) { - *pp_err_str = NULL; - } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + + sam_pass = samu_new(tosctx); + if (!sam_pass) { + result = NT_STATUS_NO_MEMORY; + goto done; } - } else { - if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) { + + /* Now get back the smb passwd entry for this new user */ + user_exists = pdb_getsampwnam(sam_pass, user_name); + if (!user_exists) { + ret = asprintf(pp_err_str, + "Failed to add entry for user %s.\n", + user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } } + acb = pdb_get_acct_ctrl(sam_pass); + /* * We are root - just write the new password * and the valid last change time. */ - - if (local_flags & LOCAL_DISABLE_USER) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) { - *pp_err_str = NULL; - } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; - } - } else if (local_flags & LOCAL_ENABLE_USER) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) { + if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) { + acb |= ACB_PWNOTREQ; + if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) { + ret = asprintf(pp_err_str, + "Failed to set 'no password required' " + "flag for user %s.\n", user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } } - if (local_flags & LOCAL_SET_NO_PASSWORD) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) { - *pp_err_str = NULL; - } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; - } - } else if (local_flags & LOCAL_SET_PASSWORD) { + if (local_flags & LOCAL_SET_PASSWORD) { /* * If we're dealing with setting a completely empty user account * ie. One with a password of 'XXXX', but not set disabled (like @@ -772,83 +781,106 @@ NTSTATUS local_password_change(const char *user_name, * and the decision hasn't really been made to disable them (ie. * don't create them disabled). JRA. */ - if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) { + if ((pdb_get_lanman_passwd(sam_pass) == NULL) && + (acb & ACB_DISABLED)) { + acb &= (~ACB_DISABLED); + if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) { + ret = asprintf(pp_err_str, + "Failed to unset 'disabled' " + "flag for user %s.\n", + user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; - } - } - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) { - if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) { - *pp_err_str = NULL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; } - if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) { - if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) { + acb &= (~ACB_PWNOTREQ); + if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) { + ret = asprintf(pp_err_str, + "Failed to unset 'no password required'" + " flag for user %s.\n", user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - } - if (local_flags & LOCAL_ADD_USER) { - if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) { - if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) { - *pp_msg_str = NULL; - } - TALLOC_FREE(sam_pass); - return NT_STATUS_OK; - } else { - if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) { + if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) { + ret = asprintf(pp_err_str, + "Failed to set password for " + "user %s.\n", user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - } else if (local_flags & LOCAL_DELETE_USER) { - if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) { - if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) { + } + + if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) { + acb |= ACB_DISABLED; + if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) { + ret = asprintf(pp_err_str, + "Failed to set 'disabled' flag for " + "user %s.\n", user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return NT_STATUS_UNSUCCESSFUL; - } - if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) { - *pp_msg_str = NULL; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - } else { - result = pdb_update_sam_account(sam_pass); - if(!NT_STATUS_IS_OK(result)) { - if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) { + } + + if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) { + acb &= (~ACB_DISABLED); + if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) { + ret = asprintf(pp_err_str, + "Failed to unset 'disabled' flag for " + "user %s.\n", user_name); + if (ret < 0) { *pp_err_str = NULL; } - TALLOC_FREE(sam_pass); - return result; + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - if(local_flags & LOCAL_DISABLE_USER) { - if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) { - *pp_msg_str = NULL; - } - } else if (local_flags & LOCAL_ENABLE_USER) { - if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) { - *pp_msg_str = NULL; - } - } else if (local_flags & LOCAL_SET_NO_PASSWORD) { - if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) { - *pp_msg_str = NULL; - } + } + + /* now commit changes if any */ + result = pdb_update_sam_account(sam_pass); + if (!NT_STATUS_IS_OK(result)) { + ret = asprintf(pp_err_str, + "Failed to modify entry for user %s.\n", + user_name); + if (ret < 0) { + *pp_err_str = NULL; } + goto done; + } + + if (local_flags & LOCAL_ADD_USER) { + ret = asprintf(pp_msg_str, "Added user %s.\n", user_name); + } else if (local_flags & LOCAL_DISABLE_USER) { + ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name); + } else if (local_flags & LOCAL_ENABLE_USER) { + ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name); + } else if (local_flags & LOCAL_SET_NO_PASSWORD) { + ret = asprintf(pp_msg_str, + "User %s password set to none.\n", user_name); } + if (ret < 0) { + *pp_msg_str = NULL; + } + + result = NT_STATUS_OK; + +done: TALLOC_FREE(sam_pass); - return NT_STATUS_OK; + return result; } /********************************************************************** diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index b4e1bd436c..b69e41590f 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -1330,26 +1330,6 @@ static bool pdb_default_sid_to_id(struct pdb_methods *methods, return ret; } -static bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, - uid_t uid, uid_t **pp_uids, size_t *p_num) -{ - size_t i; - - for (i=0; i<*p_num; i++) { - if ((*pp_uids)[i] == uid) - return True; - } - - *pp_uids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_uids, uid_t, *p_num+1); - - if (*pp_uids == NULL) - return False; - - (*pp_uids)[*p_num] = uid; - *p_num += 1; - return True; -} - static bool get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size_t *p_num) { struct group *grp; diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index c853258a34..0bebcc7c2c 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -7,20 +7,20 @@ Copyright (C) Andrew Bartlett 2002-2003 Copyright (C) Stefan (metze) Metzmacher 2002-2003 Copyright (C) Simo Sorce 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - + */ /* TODO: @@ -98,10 +98,10 @@ static const char* get_userattr_key2string( int schema_ver, int key ) switch ( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: return get_attr_key2string( attrib_map_v22, key ); - + case SCHEMAVER_SAMBASAMACCOUNT: return get_attr_key2string( attrib_map_v30, key ); - + default: DEBUG(0,("get_userattr_key2string: unknown schema version specified\n")); break; @@ -118,14 +118,14 @@ const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver ) switch ( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: return get_attr_list( mem_ctx, attrib_map_v22 ); - + case SCHEMAVER_SAMBASAMACCOUNT: return get_attr_list( mem_ctx, attrib_map_v30 ); default: DEBUG(0,("get_userattr_list: unknown schema version specified!\n")); break; } - + return NULL; } @@ -140,7 +140,7 @@ static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx, case SCHEMAVER_SAMBAACCOUNT: return get_attr_list( mem_ctx, attrib_map_to_delete_v22 ); - + case SCHEMAVER_SAMBASAMACCOUNT: return get_attr_list( mem_ctx, attrib_map_to_delete_v30 ); @@ -148,7 +148,7 @@ static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx, DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n")); break; } - + return NULL; } @@ -162,7 +162,7 @@ static const char* get_objclass_filter( int schema_ver ) { fstring objclass_filter; char *result; - + switch( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); @@ -175,7 +175,7 @@ static const char* get_objclass_filter( int schema_ver ) objclass_filter[0] = '\0'; break; } - + result = talloc_strdup(talloc_tos(), objclass_filter); SMB_ASSERT(result != NULL); return result; @@ -448,7 +448,7 @@ static int ldapsam_delete_entry(struct ldapsam_privates *priv, } /* Ok, delete only the SAM attributes */ - + for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr); name != NULL; name = ldap_next_attribute(priv2ld(priv), entry, ptr)) { @@ -1501,7 +1501,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu int count; const char ** attr_list; int rc; - + attr_list = get_userattr_list( user, ldap_state->schema_ver ); append_attr(user, &attr_list, get_userattr_key2string(ldap_state->schema_ver, @@ -1513,9 +1513,9 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu if ( rc != LDAP_SUCCESS ) return NT_STATUS_NO_SUCH_USER; - + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); - + if (count < 1) { DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count)); ldap_msgfree(result); @@ -1572,12 +1572,12 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, return rc; break; } - + case SCHEMAVER_SAMBAACCOUNT: if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) { return rc; } - + attr_list = get_userattr_list(NULL, ldap_state->schema_ver); rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list ); @@ -1608,7 +1608,7 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu return NT_STATUS_NO_SUCH_USER; count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); - + if (count < 1) { DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] " "count=%d\n", sid_string_dbg(sid), count)); @@ -1652,11 +1652,11 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; int rc; - + if (!newpwd || !dn) { return NT_STATUS_INVALID_PARAMETER; } - + if (!mods) { DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n")); /* may be password change below however */ @@ -1684,12 +1684,12 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, ldap_op)); return NT_STATUS_INVALID_PARAMETER; } - + if (rc!=LDAP_SUCCESS) { return NT_STATUS_UNSUCCESSFUL; } } - + if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) && (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) && need_update(newpwd, PDB_PLAINTEXT_PW) && @@ -1749,7 +1749,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, TALLOC_FREE(utf8_password); return NT_STATUS_UNSUCCESSFUL; } - + TALLOC_FREE(utf8_dn); TALLOC_FREE(utf8_password); ber_free(ber, 1); @@ -1846,7 +1846,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, result = NT_STATUS_NO_SUCH_USER; goto done; } - + rc = ldapsam_delete_entry( priv, mem_ctx, entry, priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ? @@ -1932,7 +1932,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc TALLOC_FREE(dn); return NT_STATUS_OK; } - + ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed); if (mods != NULL) { @@ -2670,7 +2670,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, ret = NT_STATUS_NO_MEMORY; goto done; } - + filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid); if (filter == NULL) { SAFE_FREE(escape_memberuid); @@ -2775,7 +2775,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, } ret = NT_STATUS_OK; - + done: if (values) @@ -3268,7 +3268,7 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods, rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP, get_attr_list(mem_ctx, groupmap_attr_list_to_delete)); - + if ((rc == LDAP_NAMING_VIOLATION) || (rc == LDAP_NOT_ALLOWED_ON_RDN) || (rc == LDAP_OBJECT_CLASS_VIOLATION)) { @@ -3376,11 +3376,11 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, while (!bret) { if (!ldap_state->entry) return ret; - + ldap_state->index++; bret = init_group_from_ldap(ldap_state, map, ldap_state->entry); - + ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->entry); @@ -3874,7 +3874,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods } *value = (uint32)atol(vals[0]); - + ntstatus = NT_STATUS_OK; out: @@ -3889,7 +3889,7 @@ out: - if user hasn't decided to use account policies inside LDAP just reuse the old tdb values - + - if there is a valid cache entry, return that - if there is an LDAP entry, update cache and return - otherwise set to default, update cache and return @@ -3928,16 +3928,16 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, if (!account_policy_get_default(policy_index, value)) { return ntstatus; } - + /* update_ldap: */ - + ntstatus = ldapsam_set_account_policy(methods, policy_index, *value); if (!NT_STATUS_IS_OK(ntstatus)) { return ntstatus; } - + update_cache: - + if (!cache_account_policy_set(policy_index, *value)) { DEBUG(0,("ldapsam_get_account_policy: failed to update local " "tdb as a cache\n")); @@ -4467,7 +4467,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state, DEBUG(0, ("talloc failed\n")); return False; } - + vals = ldap_get_values(ld, entry, "sambaSid"); if ((vals == NULL) || (vals[0] == NULL)) { DEBUG(0, ("\"objectSid\" not found\n")); @@ -4623,7 +4623,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state, DEBUG(0, ("talloc failed\n")); return False; } - + vals = ldap_get_values(ld, entry, "sambaSid"); if ((vals == NULL) || (vals[0] == NULL)) { DEBUG(0, ("\"objectSid\" not found\n")); @@ -4652,7 +4652,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state, return False; } break; - + default: DEBUG(0,("unkown group type: %d\n", group_type)); return False; @@ -4980,7 +4980,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods, uid_t uid = -1; NTSTATUS ret; int rc; - + if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') || acb_info & ACB_WSTRUST || acb_info & ACB_SVRTRUST || @@ -5006,7 +5006,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods, DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - + if (num_result == 1) { char *tmp; /* check if it is just a posix account. @@ -5035,7 +5035,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods, if (num_result == 0) { add_posix = True; } - + /* Create the basic samu structure and generate the mods for the ldap commit */ if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) { DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n")); @@ -5181,7 +5181,7 @@ static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX * int rc; DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct))); - + filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)" "(objectClass=%s)" @@ -5263,7 +5263,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods, DOM_SID group_sid; gid_t gid = -1; int rc; - + groupname = escape_ldap_string_alloc(name); filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))", groupname, LDAP_OBJ_POSIXGROUP); @@ -5282,7 +5282,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods, DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - + if (num_result == 1) { char *tmp; /* check if it is just a posix group. @@ -5306,7 +5306,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods, DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - + gid = strtoul(tmp, NULL, 10); dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry); @@ -5322,7 +5322,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods, DEBUG(3,("ldapsam_create_user: Creating new posix group\n")); is_new_entry = True; - + /* lets allocate a new groupid for this group */ if (!winbind_allocate_gid(&gid)) { DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n")); @@ -5519,7 +5519,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods, default: return NT_STATUS_UNSUCCESSFUL; } - + /* get member sid */ sid_compose(&member_sid, get_global_sam_sid(), member_rid); @@ -5566,7 +5566,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods, /* check if we are trying to remove the member from his primary group */ char *gidstr; gid_t user_gid, group_gid; - + gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx); if (!gidstr) { DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n")); @@ -5574,7 +5574,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods, } user_gid = strtoul(gidstr, NULL, 10); - + if (!sid_to_gid(&group_sid, &group_gid)) { DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n")); return NT_STATUS_UNSUCCESSFUL; @@ -5649,7 +5649,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods, } return NT_STATUS_UNSUCCESSFUL; } - + return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index d8c48058be..94e73fb54d 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -46,7 +46,7 @@ struct handle_list { /* This is the max handles across all instances of a pipe name. */ #ifndef MAX_OPEN_POLS -#define MAX_OPEN_POLS 1024 +#define MAX_OPEN_POLS 2048 #endif /**************************************************************************** diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 333eabe2ce..7f45a4809c 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -882,6 +882,13 @@ NTSTATUS _netr_LogonSamLogon(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } + *r->out.authoritative = true; /* authoritative response */ + if (r->in.validation_level != 2 && r->in.validation_level != 3) { + DEBUG(0,("%s: bad validation_level value %d.\n", + fn, (int)r->in.validation_level)); + return NT_STATUS_INVALID_INFO_CLASS; + } + sam3 = TALLOC_ZERO_P(p->mem_ctx, struct netr_SamInfo3); if (!sam3) { return NT_STATUS_NO_MEMORY; @@ -889,12 +896,6 @@ NTSTATUS _netr_LogonSamLogon(pipes_struct *p, /* store the user information, if there is any. */ r->out.validation->sam3 = sam3; - *r->out.authoritative = true; /* authoritative response */ - if (r->in.validation_level != 2 && r->in.validation_level != 3) { - DEBUG(0,("%s: bad validation_level value %d.\n", - fn, (int)r->in.validation_level)); - return NT_STATUS_ACCESS_DENIED; - } if (process_creds) { diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 9e86f3fb1f..6b7c140bc1 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -128,6 +128,7 @@ SMB_INCLUDE_MK(lib/ldb/python.mk) SMB_ENABLE(swig_ldb,YES) m4_include(lib/tls/config.m4) +m4_include(torture/libnetapi/config.m4) dnl m4_include(auth/kerberos/config.m4) m4_include(auth/gensec/config.m4) diff --git a/source3/samba4.mk b/source3/samba4.mk index 3f661bdd14..e63a8453c0 100644 --- a/source3/samba4.mk +++ b/source3/samba4.mk @@ -74,6 +74,7 @@ clustersrcdir := $(samba4srcdir)/cluster libnetsrcdir := $(samba4srcdir)/libnet authsrcdir := $(samba4srcdir)/auth nsswitchsrcdir := $(samba4srcdir)/../nsswitch +libwbclientsrcdir := $(nsswitchsrcdir)/libwbclient libsrcdir := $(samba4srcdir)/lib libsocketsrcdir := $(samba4srcdir)/lib/socket libcharsetsrcdir := $(samba4srcdir)/../lib/util/charset diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index 956c5af77b..e3871132d2 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -289,6 +289,7 @@ EOF cat >$NSS_WRAPPER_GROUP<<EOF nobody:x:65533: nogroup:x:65534:nobody +root:x:65532: $USERNAME-group:x:$GROUPID: EOF diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 0bcf3695ed..83593dde4d 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -45,12 +45,14 @@ rpc="$rpc RPC-LSA-GETUSER RPC-LSA-LOOKUPSIDS RPC-LSA-LOOKUPNAMES" rpc="$rpc RPC-SAMR-USERS RPC-SAMR-USERS-PRIVILEGES RPC-SAMR-PASSWORDS RPC-SAMR-PASSWORDS-PWDLASTSET RPC-SAMR-LARGE-DC RPC-JOIN" rpc="$rpc RPC-SCHANNEL RPC-SCHANNEL2 RPC-BENCH-SCHANNEL1" +local="LOCAL-NSS-WRAPPER" + # NOTE: to enable the UNIX-WHOAMI test, we need to change the default share # config to allow guest access. I'm not sure whether this would break other # tests, so leaving it alone for now -- jpeach unix="UNIX-INFO2" -tests="$base $raw $rpc $unix" +tests="$base $raw $rpc $unix $local" if test "x$POSIX_SUBTESTS" != "x" ; then tests="$POSIX_SUBTESTS" diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6468544748..eeed76329c 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -379,7 +379,7 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode) } /**************************************************************************** - Gets DOS attributes, accessed via st_flags in the stat struct. + Gets DOS attributes, accessed via st_ex_flags in the stat struct. ****************************************************************************/ static bool get_stat_dos_flags(connection_struct *conn, @@ -396,15 +396,15 @@ static bool get_stat_dos_flags(connection_struct *conn, DEBUG(5, ("Getting stat dos attributes for %s.\n", fname)); - if (sbuf->st_flags & UF_DOS_ARCHIVE) + if (sbuf->st_ex_flags & UF_DOS_ARCHIVE) *dosmode |= aARCH; - if (sbuf->st_flags & UF_DOS_HIDDEN) + if (sbuf->st_ex_flags & UF_DOS_HIDDEN) *dosmode |= aHIDDEN; - if (sbuf->st_flags & UF_DOS_RO) + if (sbuf->st_ex_flags & UF_DOS_RO) *dosmode |= aRONLY; - if (sbuf->st_flags & UF_DOS_SYSTEM) + if (sbuf->st_ex_flags & UF_DOS_SYSTEM) *dosmode |= aSYSTEM; - if (sbuf->st_flags & UF_DOS_NOINDEX) + if (sbuf->st_ex_flags & UF_DOS_NOINDEX) *dosmode |= FILE_ATTRIBUTE_NONINDEXED; if (S_ISDIR(sbuf->st_ex_mode)) *dosmode |= aDIR; @@ -416,7 +416,7 @@ static bool get_stat_dos_flags(connection_struct *conn, } /**************************************************************************** - Sets DOS attributes, stored in st_flags of the inode. + Sets DOS attributes, stored in st_ex_flags of the inode. ****************************************************************************/ static bool set_stat_dos_flags(connection_struct *conn, @@ -439,15 +439,15 @@ static bool set_stat_dos_flags(connection_struct *conn, DEBUG(5, ("Setting stat dos attributes for %s.\n", fname)); - new_flags = (sbuf->st_flags & ~UF_DOS_FLAGS) | + new_flags = (sbuf->st_ex_flags & ~UF_DOS_FLAGS) | dos_attributes_to_stat_dos_flags(dosmode); /* Return early if no flags changed. */ - if (new_flags == sbuf->st_flags) + if (new_flags == sbuf->st_ex_flags) return true; DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags, - sbuf->st_flags)); + sbuf->st_ex_flags)); /* Set new flags with chflags. */ error = SMB_VFS_CHFLAGS(conn, fname, new_flags); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 72b4ab7aa6..059dca29c8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -513,8 +513,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, goto fail; } - /* ENOENT is the only valid error here. */ - if ((errno != 0) && (errno != ENOENT)) { + /* + * ENOENT/EACCESS are the only valid errors + * here. EACCESS needs handling here for + * "dropboxes", i.e. directories where users + * can only put stuff with permission -wx. + */ + if ((errno != 0) && (errno != ENOENT) + && (errno != EACCES)) { /* * ENOTDIR and ELOOP both map to * NT_STATUS_OBJECT_PATH_NOT_FOUND @@ -524,8 +530,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, errno == ELOOP) { result = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - else { + } else { result = map_nt_error_from_unix(errno); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c1b29f68f3..fdfa99953f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -346,7 +346,7 @@ static NTSTATUS open_file(files_struct *fsp, if (!CAN_WRITE(conn)) { /* It's a read-only share - fail if we wanted to write. */ - if(accmode != O_RDONLY) { + if(accmode != O_RDONLY || (flags & O_TRUNC) || (flags & O_APPEND)) { DEBUG(3,("Permission denied opening %s\n", path)); return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { @@ -354,8 +354,8 @@ static NTSTATUS open_file(files_struct *fsp, O_CREAT doesn't create the file if we have write access into the directory. */ - flags &= ~O_CREAT; - local_flags &= ~O_CREAT; + flags &= ~(O_CREAT|O_EXCL); + local_flags &= ~(O_CREAT|O_EXCL); } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d95c207ba..d11bf088e0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6870,16 +6870,20 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } } - if (!CAN_WRITE(conn)) { - reply_doserror(req, ERRSRV, ERRaccess); - return; - } - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; } + if (!CAN_WRITE(conn)) { + /* Allow POSIX opens. The open path will deny + * any non-readonly opens. */ + if (info_level != SMB_POSIX_PATH_OPEN) { + reply_doserror(req, ERRSRV, ERRaccess); + return; + } + } + DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index b05ca44f0e..d185a71727 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -18,7 +18,7 @@ */ #include "includes.h" -#include "wbc_async.h" +#include "nsswitch/libwbclient/wbc_async.h" extern char *optarg; extern int optind; @@ -3092,7 +3092,7 @@ static bool run_deletetest(int dummy) goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1)); correct = False; goto fail; @@ -3145,7 +3145,7 @@ static bool run_deletetest(int dummy) goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1)); correct = False; goto fail; @@ -3201,7 +3201,7 @@ static bool run_deletetest(int dummy) goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1)); correct = False; goto fail; @@ -3235,7 +3235,7 @@ static bool run_deletetest(int dummy) /* This should fail - only allowed on NT opens with DELETE access. */ - if (cli_nt_delete_on_close(cli1, fnum1, True)) { + if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n"); correct = False; goto fail; @@ -3263,7 +3263,7 @@ static bool run_deletetest(int dummy) /* This should fail - only allowed on NT opens with DELETE access. */ - if (cli_nt_delete_on_close(cli1, fnum1, True)) { + if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n"); correct = False; goto fail; @@ -3288,13 +3288,13 @@ static bool run_deletetest(int dummy) goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[7] setting delete_on_close on file failed !\n"); correct = False; goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, False)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) { printf("[7] unsetting delete_on_close on file failed !\n"); correct = False; goto fail; @@ -3350,7 +3350,7 @@ static bool run_deletetest(int dummy) goto fail; } - if (!cli_nt_delete_on_close(cli1, fnum1, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) { printf("[8] setting delete_on_close on file failed !\n"); correct = False; goto fail; @@ -3639,7 +3639,7 @@ static bool run_rename(int dummy) printf("Fourth open failed - %s\n", cli_errstr(cli1)); return False; } - if (!cli_nt_delete_on_close(cli1, fnum2, True)) { + if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) { printf("[8] setting delete_on_close on file failed !\n"); return False; } @@ -5985,7 +5985,7 @@ static bool run_local_wbclient(int dummy) d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops); for (i=0; i<nprocs; i++) { - wb_ctx[i] = wb_context_init(ev); + wb_ctx[i] = wb_context_init(ev, NULL); if (wb_ctx[i] == NULL) { goto fail; } diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 328b2cb1f4..23c4e71e0d 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. passdb editing frontend - - Copyright (C) Simo Sorce 2000 - Copyright (C) Andrew Bartlett 2001 + + Copyright (C) Simo Sorce 2000-2009 + Copyright (C) Andrew Bartlett 2001 Copyright (C) Jelmer Vernooij 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 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -53,13 +53,33 @@ #define MASK_ALWAYS_GOOD 0x0000001F #define MASK_USER_GOOD 0x00405FE0 +static int get_sid_from_cli_string(DOM_SID *sid, const char *str_sid) +{ + uint32_t rid; + + if (!string_to_sid(sid, str_sid)) { + /* not a complete sid, may be a RID, + * try building a SID */ + + if (sscanf(str_sid, "%u", &rid) != 1) { + fprintf(stderr, "Error passed string is not " + "a complete SID or RID!\n"); + return -1; + } + sid_copy(sid, get_global_sam_sid()); + sid_append_rid(sid, rid); + } + + return 0; +} + /********************************************************* Add all currently available users to another db ********************************************************/ -static int export_database (struct pdb_methods *in, - struct pdb_methods *out, - const char *username) +static int export_database (struct pdb_methods *in, + struct pdb_methods *out, + const char *username) { NTSTATUS status; struct pdb_search *u_search; @@ -148,13 +168,13 @@ static int export_database (struct pdb_methods *in, Add all currently available group mappings to another db ********************************************************/ -static int export_groups (struct pdb_methods *in, struct pdb_methods *out) +static int export_groups (struct pdb_methods *in, struct pdb_methods *out) { GROUP_MAP *maps = NULL; size_t i, entries = 0; NTSTATUS status; - status = in->enum_group_mapping(in, get_global_sam_sid(), + status = in->enum_group_mapping(in, get_global_sam_sid(), SID_NAME_DOM_GRP, &maps, &entries, False); if ( NT_STATUS_IS_ERR(status) ) { @@ -175,7 +195,7 @@ static int export_groups (struct pdb_methods *in, struct pdb_methods *out) Reset account policies to their default values and remove marker ********************************************************/ -static int reinit_account_policies (void) +static int reinit_account_policies (void) { int i; @@ -260,31 +280,31 @@ static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdst printf ("Munged dial: %s\n", pdb_get_munged_dial(sam_pwent)); tmp = pdb_get_logon_time(sam_pwent); - printf ("Logon time: %s\n", + printf ("Logon time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_logoff_time(sam_pwent); - printf ("Logoff time: %s\n", + printf ("Logoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_kickoff_time(sam_pwent); - printf ("Kickoff time: %s\n", + printf ("Kickoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_last_set_time(sam_pwent); - printf ("Password last set: %s\n", + printf ("Password last set: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_can_change_time(sam_pwent); - printf ("Password can change: %s\n", + printf ("Password can change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_must_change_time(sam_pwent); - printf ("Password must change: %s\n", + printf ("Password must change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_bad_password_time(sam_pwent); - printf ("Last bad password : %s\n", + printf ("Last bad password : %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); printf ("Bad password count : %d\n", pdb_get_bad_password_count(sam_pwent)); @@ -310,7 +330,7 @@ static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdst (uint32)convert_time_t_to_uint32(pdb_get_pass_last_set_time(sam_pwent))); } else { uid = nametouid(pdb_get_username(sam_pwent)); - printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, + printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, pdb_get_fullname(sam_pwent)); } @@ -321,167 +341,186 @@ static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdst Get an Print User Info **********************************************************/ -static int print_user_info (struct pdb_methods *in, const char *username, bool verbosity, bool smbpwdstyle) +static int print_user_info(const char *username, + bool verbosity, bool smbpwdstyle) { - struct samu *sam_pwent=NULL; - bool ret; + struct samu *sam_pwent = NULL; + bool bret; + int ret; - if ( (sam_pwent = samu_new( NULL )) == NULL ) { + sam_pwent = samu_new(NULL); + if (!sam_pwent) { return -1; } - ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username)); - - if (ret==False) { + bret = pdb_getsampwnam(sam_pwent, username); + if (!bret) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } - ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle); + ret = print_sam_info(sam_pwent, verbosity, smbpwdstyle); + TALLOC_FREE(sam_pwent); - return ret; } - + /********************************************************* List Users **********************************************************/ -static int print_users_list (struct pdb_methods *in, bool verbosity, bool smbpwdstyle) +static int print_users_list(bool verbosity, bool smbpwdstyle) { struct pdb_search *u_search; struct samr_displayentry userentry; - - u_search = pdb_search_init(talloc_tos(), PDB_USER_SEARCH); - if (u_search == NULL) { - DEBUG(0, ("pdb_search_init failed\n")); + struct samu *sam_pwent; + TALLOC_CTX *tosctx; + DOM_SID user_sid; + bool bret; + int ret; + + tosctx = talloc_tos(); + if (!tosctx) { + DEBUG(0, ("talloc failed\n")); return 1; } - if (!in->search_users(in, u_search, 0)) { - DEBUG(0, ("Could not start searching users\n")); - TALLOC_FREE(u_search); - return 1; + u_search = pdb_search_users(tosctx, 0); + if (!u_search) { + DEBUG(0, ("User Search failed!\n")); + ret = 1; + goto done; } while (u_search->next_entry(u_search, &userentry)) { - struct samu *sam_pwent; - DOM_SID user_sid; - NTSTATUS status; - sam_pwent = samu_new(talloc_tos()); + sam_pwent = samu_new(tosctx); if (sam_pwent == NULL) { DEBUG(0, ("talloc failed\n")); - break; + ret = 1; + goto done; } sid_compose(&user_sid, get_global_sam_sid(), userentry.rid); - status = in->getsampwsid(in, sam_pwent, &user_sid); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2, ("getsampwsid failed: %s\n", - nt_errstr(status))); + bret = pdb_getsampwsid(sam_pwent, &user_sid); + if (!bret) { + DEBUG(2, ("getsampwsid failed\n")); TALLOC_FREE(sam_pwent); continue; } - if (verbosity) + if (verbosity) { printf ("---------------\n"); - print_sam_info (sam_pwent, verbosity, smbpwdstyle); + } + print_sam_info(sam_pwent, verbosity, smbpwdstyle); TALLOC_FREE(sam_pwent); } - TALLOC_FREE(u_search); - return 0; + ret = 0; + +done: + TALLOC_FREE(tosctx); + return ret; } /********************************************************* Fix a list of Users for uninitialised passwords **********************************************************/ -static int fix_users_list (struct pdb_methods *in) +static int fix_users_list(void) { struct pdb_search *u_search; struct samr_displayentry userentry; + struct samu *sam_pwent; + TALLOC_CTX *tosctx; + DOM_SID user_sid; + NTSTATUS status; + bool bret; + int ret; - u_search = pdb_search_init(talloc_tos(), PDB_USER_SEARCH); - if (u_search == NULL) { - DEBUG(0, ("pdb_search_init failed\n")); + tosctx = talloc_tos(); + if (!tosctx) { + fprintf(stderr, "Out of memory!\n"); return 1; } - if (!in->search_users(in, u_search, 0)) { - DEBUG(0, ("Could not start searching users\n")); - TALLOC_FREE(u_search); - return 1; + u_search = pdb_search_users(tosctx, 0); + if (!u_search) { + fprintf(stderr, "User Search failed!\n"); + ret = 1; + goto done; } while (u_search->next_entry(u_search, &userentry)) { - struct samu *sam_pwent; - DOM_SID user_sid; - NTSTATUS status; - sam_pwent = samu_new(talloc_tos()); + sam_pwent = samu_new(tosctx); if (sam_pwent == NULL) { - DEBUG(0, ("talloc failed\n")); - break; + fprintf(stderr, "Out of memory!\n"); + ret = 1; + goto done; } sid_compose(&user_sid, get_global_sam_sid(), userentry.rid); - status = in->getsampwsid(in, sam_pwent, &user_sid); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2, ("getsampwsid failed: %s\n", - nt_errstr(status))); + bret = pdb_getsampwsid(sam_pwent, &user_sid); + if (!bret) { + DEBUG(2, ("getsampwsid failed\n")); TALLOC_FREE(sam_pwent); continue; } - if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) { + status = pdb_update_sam_account(sam_pwent); + if (!NT_STATUS_IS_OK(status)) { printf("Update of user %s failed!\n", pdb_get_username(sam_pwent)); } TALLOC_FREE(sam_pwent); } - TALLOC_FREE(u_search); - return 0; + + ret = 0; + +done: + TALLOC_FREE(tosctx); + return ret; } /********************************************************* Set User Info **********************************************************/ -static int set_user_info (struct pdb_methods *in, const char *username, - const char *fullname, const char *homedir, - const char *acct_desc, - const char *drive, const char *script, - const char *profile, const char *account_control, - const char *user_sid, const char *user_domain, - const bool badpw, const bool hours) +static int set_user_info(const char *username, const char *fullname, + const char *homedir, const char *acct_desc, + const char *drive, const char *script, + const char *profile, const char *account_control, + const char *user_sid, const char *user_domain, + const bool badpw, const bool hours) { bool updated_autolock = False, updated_badpw = False; - struct samu *sam_pwent=NULL; + struct samu *sam_pwent; + uint8_t hours_array[MAX_HOURS_LEN]; + uint32_t hours_len; + uint32_t acb_flags; + uint32_t not_settable; + uint32_t new_flags; + DOM_SID u_sid; bool ret; - - if ( (sam_pwent = samu_new( NULL )) == NULL ) { + + sam_pwent = samu_new(NULL); + if (!sam_pwent) { return 1; } - - ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username)); - if (ret==False) { + + ret = pdb_getsampwnam(sam_pwent, username); + if (!ret) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } if (hours) { - uint8 hours_array[MAX_HOURS_LEN]; - uint32 hours_len; - hours_len = pdb_get_hours_len(sam_pwent); memset(hours_array, 0xff, hours_len); - + pdb_set_hours(sam_pwent, hours_array, PDB_CHANGED); } @@ -509,35 +548,29 @@ static int set_user_info (struct pdb_methods *in, const char *username, pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED); if (account_control) { - uint32 not_settable = ~(ACB_DISABLED|ACB_HOMDIRREQ|ACB_PWNOTREQ| - ACB_PWNOEXP|ACB_AUTOLOCK); + not_settable = ~(ACB_DISABLED | ACB_HOMDIRREQ | + ACB_PWNOTREQ | ACB_PWNOEXP | ACB_AUTOLOCK); - uint32 newflag = pdb_decode_acct_ctrl(account_control); + new_flags = pdb_decode_acct_ctrl(account_control); - if (newflag & not_settable) { + if (new_flags & not_settable) { fprintf(stderr, "Can only set [NDHLX] flags\n"); TALLOC_FREE(sam_pwent); return -1; } + acb_flags = pdb_get_acct_ctrl(sam_pwent); + pdb_set_acct_ctrl(sam_pwent, - (pdb_get_acct_ctrl(sam_pwent) & not_settable) | newflag, + (acb_flags & not_settable) | new_flags, PDB_CHANGED); } if (user_sid) { - DOM_SID u_sid; - if (!string_to_sid(&u_sid, user_sid)) { - /* not a complete sid, may be a RID, try building a SID */ - int u_rid; - - if (sscanf(user_sid, "%d", &u_rid) != 1) { - fprintf(stderr, "Error passed string is not a complete user SID or RID!\n"); - return -1; - } - sid_copy(&u_sid, get_global_sam_sid()); - sid_append_rid(&u_sid, u_rid); + if (get_sid_from_cli_string(&u_sid, user_sid)) { + fprintf(stderr, "Failed to parse SID\n"); + return -1; } - pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED); + pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED); } if (badpw) { @@ -545,9 +578,9 @@ static int set_user_info (struct pdb_methods *in, const char *username, pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED); } - if (NT_STATUS_IS_OK(in->update_sam_account (in, sam_pwent))) - print_user_info (in, username, True, False); - else { + if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) { + print_user_info(username, True, False); + } else { fprintf (stderr, "Unable to modify entry!\n"); TALLOC_FREE(sam_pwent); return -1; @@ -556,180 +589,315 @@ static int set_user_info (struct pdb_methods *in, const char *username, return 0; } -/********************************************************* - Add New User -**********************************************************/ -static int new_user (struct pdb_methods *in, const char *username, - const char *fullname, const char *homedir, - const char *drive, const char *script, - const char *profile, char *user_sid, bool stdin_get) +static int set_machine_info(const char *machinename, + const char *account_control, + const char *machine_sid) { - struct samu *sam_pwent; - char *password1, *password2; - int rc_pwd_cmp; - struct passwd *pwd; - - get_global_sam_sid(); + struct samu *sam_pwent = NULL; + TALLOC_CTX *tosctx; + uint32_t acb_flags; + uint32_t not_settable; + uint32_t new_flags; + DOM_SID m_sid; + char *name; + int len; + bool ret; - if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), username )) ) { - DEBUG(0,("Cannot locate Unix account for %s\n", username)); + len = strlen(machinename); + if (len == 0) { + fprintf(stderr, "No machine name given\n"); return -1; } - if ( (sam_pwent = samu_new( NULL )) == NULL ) { - DEBUG(0, ("Memory allocation failure!\n")); + tosctx = talloc_tos(); + if (!tosctx) { + fprintf(stderr, "Out of memory!\n"); return -1; } - if (!NT_STATUS_IS_OK(samu_alloc_rid_unix(sam_pwent, pwd ))) { - TALLOC_FREE( sam_pwent ); - TALLOC_FREE( pwd ); - DEBUG(0, ("could not create account to add new user %s\n", username)); + sam_pwent = samu_new(tosctx); + if (!sam_pwent) { + return 1; + } + + if (machinename[len-1] == '$') { + name = talloc_strdup(sam_pwent, machinename); + } else { + name = talloc_asprintf(sam_pwent, "%s$", machinename); + } + if (!name) { + fprintf(stderr, "Out of memory!\n"); + TALLOC_FREE(sam_pwent); return -1; } - password1 = get_pass( "new password:", stdin_get); - password2 = get_pass( "retype new password:", stdin_get); - if ((rc_pwd_cmp = strcmp (password1, password2))) { - fprintf (stderr, "Passwords do not match!\n"); + strlower_m(name); + + ret = pdb_getsampwnam(sam_pwent, name); + if (!ret) { + fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); + return -1; + } + + if (account_control) { + not_settable = ~(ACB_DISABLED); + + new_flags = pdb_decode_acct_ctrl(account_control); + + if (new_flags & not_settable) { + fprintf(stderr, "Can only set [D] flags\n"); + TALLOC_FREE(sam_pwent); + return -1; + } + + acb_flags = pdb_get_acct_ctrl(sam_pwent); + + pdb_set_acct_ctrl(sam_pwent, + (acb_flags & not_settable) | new_flags, + PDB_CHANGED); + } + if (machine_sid) { + if (get_sid_from_cli_string(&m_sid, machine_sid)) { + fprintf(stderr, "Failed to parse SID\n"); + return -1; + } + pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED); + } + + if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) { + print_user_info(name, True, False); } else { - pdb_set_plaintext_passwd(sam_pwent, password1); + fprintf (stderr, "Unable to modify entry!\n"); + TALLOC_FREE(sam_pwent); + return -1; } + TALLOC_FREE(sam_pwent); + return 0; +} - memset(password1, 0, strlen(password1)); - SAFE_FREE(password1); - memset(password2, 0, strlen(password2)); - SAFE_FREE(password2); +/********************************************************* + Add New User +**********************************************************/ +static int new_user(const char *username, const char *fullname, + const char *homedir, const char *drive, + const char *script, const char *profile, + char *user_sid, bool stdin_get) +{ + char *pwd1 = NULL, *pwd2 = NULL; + char *err = NULL, *msg = NULL; + struct samu *sam_pwent = NULL; + TALLOC_CTX *tosctx; + NTSTATUS status; + DOM_SID u_sid; + int flags; + int ret; - /* pwds do _not_ match? */ - if (rc_pwd_cmp) + tosctx = talloc_tos(); + if (!tosctx) { + fprintf(stderr, "Out of memory!\n"); return -1; + } + + if (user_sid) { + if (get_sid_from_cli_string(&u_sid, user_sid)) { + fprintf(stderr, "Failed to parse SID\n"); + return -1; + } + } + + pwd1 = get_pass( "new password:", stdin_get); + pwd2 = get_pass( "retype new password:", stdin_get); + ret = strcmp(pwd1, pwd2); + if (ret != 0) { + fprintf (stderr, "Passwords do not match!\n"); + goto done; + } + + flags = LOCAL_ADD_USER | LOCAL_SET_PASSWORD; + + status = local_password_change(username, flags, pwd1, &err, &msg); + if (!NT_STATUS_IS_OK(status)) { + if (err) fprintf(stderr, "%s", err); + ret = -1; + goto done; + } + + sam_pwent = samu_new(tosctx); + if (!sam_pwent) { + fprintf(stderr, "Out of memory!\n"); + ret = -1; + goto done; + } + + if (!pdb_getsampwnam(sam_pwent, username)) { + fprintf(stderr, "User %s not found!\n", username); + ret = -1; + goto done; + } if (fullname) pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED); if (homedir) - pdb_set_homedir (sam_pwent, homedir, PDB_CHANGED); + pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED); if (drive) - pdb_set_dir_drive (sam_pwent, drive, PDB_CHANGED); + pdb_set_dir_drive(sam_pwent, drive, PDB_CHANGED); if (script) pdb_set_logon_script(sam_pwent, script, PDB_CHANGED); if (profile) - pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED); - if (user_sid) { - DOM_SID u_sid; - if (!string_to_sid(&u_sid, user_sid)) { - /* not a complete sid, may be a RID, try building a SID */ - int u_rid; - - if (sscanf(user_sid, "%d", &u_rid) != 1) { - fprintf(stderr, "Error passed string is not a complete user SID or RID!\n"); - TALLOC_FREE(sam_pwent); - return -1; - } - sid_copy(&u_sid, get_global_sam_sid()); - sid_append_rid(&u_sid, u_rid); - } - pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED); - } - - pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL, PDB_CHANGED); - - if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) { - print_user_info (in, username, True, False); - } else { - fprintf (stderr, "Unable to add user! (does it already exist?)\n"); - TALLOC_FREE(sam_pwent); - return -1; + pdb_set_profile_path(sam_pwent, profile, PDB_CHANGED); + if (user_sid) + pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED); + + status = pdb_update_sam_account(sam_pwent); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "Failed to modify entry for user %s.!\n", + username); + ret = -1; + goto done; } + + print_user_info(username, True, False); + ret = 0; + +done: + if (pwd1) memset(pwd1, 0, strlen(pwd1)); + if (pwd2) memset(pwd2, 0, strlen(pwd2)); + SAFE_FREE(pwd1); + SAFE_FREE(pwd2); + SAFE_FREE(err); + SAFE_FREE(msg); TALLOC_FREE(sam_pwent); - return 0; + return ret; } /********************************************************* Add New Machine **********************************************************/ -static int new_machine (struct pdb_methods *in, const char *machine_in) +static int new_machine(const char *machinename, char *machine_sid) { - struct samu *sam_pwent=NULL; - fstring machinename; - fstring machineaccount; - struct passwd *pwd = NULL; - - get_global_sam_sid(); - - if (strlen(machine_in) == 0) { + char *err = NULL, *msg = NULL; + struct samu *sam_pwent = NULL; + TALLOC_CTX *tosctx; + NTSTATUS status; + DOM_SID m_sid; + char *compatpwd; + char *name; + int flags; + int len; + int ret; + + len = strlen(machinename); + if (len == 0) { fprintf(stderr, "No machine name given\n"); return -1; } - fstrcpy(machinename, machine_in); - machinename[15]= '\0'; + tosctx = talloc_tos(); + if (!tosctx) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } - if (machinename[strlen (machinename) -1] == '$') - machinename[strlen (machinename) -1] = '\0'; - - strlower_m(machinename); - - fstrcpy(machineaccount, machinename); - fstrcat(machineaccount, "$"); + if (machine_sid) { + if (get_sid_from_cli_string(&m_sid, machine_sid)) { + fprintf(stderr, "Failed to parse SID\n"); + return -1; + } + } - if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), machineaccount )) ) { - DEBUG(0,("Cannot locate Unix account for %s\n", machineaccount)); + compatpwd = talloc_strdup(tosctx, machinename); + if (!compatpwd) { + fprintf(stderr, "Out of memory!\n"); return -1; } - if ( (sam_pwent = samu_new( NULL )) == NULL ) { - fprintf(stderr, "Memory allocation error!\n"); - TALLOC_FREE(pwd); + if (machinename[len-1] == '$') { + name = talloc_strdup(tosctx, machinename); + compatpwd[len-1] = '\0'; + } else { + name = talloc_asprintf(tosctx, "%s$", machinename); + } + if (!name) { + fprintf(stderr, "Out of memory!\n"); return -1; } - if ( !NT_STATUS_IS_OK(samu_alloc_rid_unix(sam_pwent, pwd )) ) { - fprintf(stderr, "Could not init sam from pw\n"); - TALLOC_FREE(pwd); - return -1; + strlower_m(name); + + flags = LOCAL_ADD_USER | LOCAL_TRUST_ACCOUNT | LOCAL_SET_PASSWORD; + + status = local_password_change(name, flags, compatpwd, &err, &msg); + + if (!NT_STATUS_IS_OK(status)) { + if (err) fprintf(stderr, "%s", err); + ret = -1; } - TALLOC_FREE(pwd); + sam_pwent = samu_new(tosctx); + if (!sam_pwent) { + fprintf(stderr, "Out of memory!\n"); + ret = -1; + goto done; + } - pdb_set_plaintext_passwd (sam_pwent, machinename); - pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED); - pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST, PDB_CHANGED); - - if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) { - print_user_info (in, machineaccount, True, False); - } else { - fprintf (stderr, "Unable to add machine! (does it already exist?)\n"); - TALLOC_FREE(sam_pwent); - return -1; + if (!pdb_getsampwnam(sam_pwent, name)) { + fprintf(stderr, "Machine %s not found!\n", name); + ret = -1; + goto done; } + + if (machine_sid) + pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED); + + status = pdb_update_sam_account(sam_pwent); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "Failed to modify entry for %s.!\n", name); + ret = -1; + goto done; + } + + print_user_info(name, True, False); + ret = 0; + +done: + SAFE_FREE(err); + SAFE_FREE(msg); TALLOC_FREE(sam_pwent); - return 0; + return ret; } /********************************************************* Delete user entry **********************************************************/ -static int delete_user_entry (struct pdb_methods *in, const char *username) +static int delete_user_entry(const char *username) { - struct samu *samaccount = NULL; + struct samu *samaccount; - if ( (samaccount = samu_new( NULL )) == NULL ) { + samaccount = samu_new(NULL); + if (!samaccount) { + fprintf(stderr, "Out of memory!\n"); return -1; } - if (!NT_STATUS_IS_OK(in->getsampwnam(in, samaccount, username))) { - fprintf (stderr, "user %s does not exist in the passdb\n", username); + if (!pdb_getsampwnam(samaccount, username)) { + fprintf (stderr, + "user %s does not exist in the passdb\n", username); + TALLOC_FREE(samaccount); return -1; } - if (!NT_STATUS_IS_OK(in->delete_sam_account (in, samaccount))) { + if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) { fprintf (stderr, "Unable to delete user %s\n", username); + TALLOC_FREE(samaccount); return -1; } + + TALLOC_FREE(samaccount); return 0; } @@ -737,35 +905,42 @@ static int delete_user_entry (struct pdb_methods *in, const char *username) Delete machine entry **********************************************************/ -static int delete_machine_entry (struct pdb_methods *in, const char *machinename) +static int delete_machine_entry(const char *machinename) { - fstring name; struct samu *samaccount = NULL; + const char *name; if (strlen(machinename) == 0) { fprintf(stderr, "No machine name given\n"); return -1; } - - fstrcpy(name, machinename); - name[15] = '\0'; - if (name[strlen(name)-1] != '$') - fstrcat (name, "$"); - if ( (samaccount = samu_new( NULL )) == NULL ) { + samaccount = samu_new(NULL); + if (!samaccount) { + fprintf(stderr, "Out of memory!\n"); return -1; } - if (!NT_STATUS_IS_OK(in->getsampwnam(in, samaccount, name))) { - fprintf (stderr, "machine %s does not exist in the passdb\n", name); + if (machinename[strlen(machinename)-1] != '$') { + name = talloc_asprintf(samaccount, "%s$", machinename); + } else { + name = machinename; + } + + if (!pdb_getsampwnam(samaccount, name)) { + fprintf (stderr, + "machine %s does not exist in the passdb\n", name); return -1; + TALLOC_FREE(samaccount); } - if (!NT_STATUS_IS_OK(in->delete_sam_account (in, samaccount))) { + if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) { fprintf (stderr, "Unable to delete machine %s\n", name); + TALLOC_FREE(samaccount); return -1; } + TALLOC_FREE(samaccount); return 0; } @@ -789,7 +964,7 @@ int main (int argc, char **argv) static const char *user_name = NULL; static char *home_dir = NULL; static char *home_drive = NULL; - static char *backend = NULL; + static const char *backend = NULL; static char *backend_in = NULL; static char *backend_out = NULL; static int transfer_groups = False; @@ -802,14 +977,16 @@ int main (int argc, char **argv) static char *account_control = NULL; static char *account_policy = NULL; static char *user_sid = NULL; + static char *machine_sid = NULL; static long int account_policy_value = 0; bool account_policy_value_set = False; static int badpw_reset = False; static int hours_reset = False; static char *pwd_time_format = NULL; static int pw_from_stdin = False; - struct pdb_methods *bin, *bout, *bdef; + struct pdb_methods *bin, *bout; TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; poptContext pc; struct poptOption long_options[] = { POPT_AUTOHELP @@ -825,6 +1002,7 @@ int main (int argc, char **argv) {"profile", 'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL}, {"domain", 'I', POPT_ARG_STRING, &user_domain, 0, "set a users' domain", NULL}, {"user SID", 'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL}, + {"machine SID", 'M', POPT_ARG_STRING, &machine_sid, 0, "set machine SID or RID", NULL}, {"create", 'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL}, {"modify", 'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL}, {"machine", 'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL}, @@ -846,16 +1024,16 @@ int main (int argc, char **argv) POPT_COMMON_SAMBA POPT_TABLEEND }; - - bin = bout = bdef = NULL; + + bin = bout = NULL; load_case_tables(); setup_logging("pdbedit", True); - + pc = poptGetContext(NULL, argc, (const char **) argv, long_options, POPT_CONTEXT_KEEP_FIRST); - + while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'C': @@ -874,9 +1052,6 @@ int main (int argc, char **argv) exit(1); } - if(!initialize_password_db(False, NULL)) - exit(1); - if (!init_names()) exit(1); @@ -894,6 +1069,7 @@ int main (int argc, char **argv) (list_users ? BIT_LIST : 0) + (force_initialised_password ? BIT_FIX_INIT : 0) + (user_sid ? BIT_USERSIDS : 0) + + (machine_sid ? BIT_USERSIDS : 0) + (modify_user ? BIT_MODIFY : 0) + (add_user ? BIT_CREATE : 0) + (delete_user ? BIT_DELETE : 0) + @@ -906,22 +1082,24 @@ int main (int argc, char **argv) (hours_reset ? BIT_LOGONHOURS : 0); if (setparms & BIT_BACKEND) { - if (!NT_STATUS_IS_OK(make_pdb_method_name( &bdef, backend ))) { - fprintf(stderr, "Can't initialize passdb backend.\n"); - return 1; - } + /* HACK: set the global passdb backend by overwriting globals. + * This way we can use regular pdb functions for default + * operations that do not involve passdb migrations */ + lp_set_passdb_backend(backend); } else { - if (!NT_STATUS_IS_OK(make_pdb_method_name(&bdef, lp_passdb_backend()))) { - fprintf(stderr, "Can't initialize passdb backend.\n"); - return 1; - } + backend = lp_passdb_backend(); } - + + if (!initialize_password_db(False, NULL)) { + fprintf(stderr, "Can't initialize passdb backend.\n"); + exit(1); + } + /* the lowest bit options are always accepted */ checkparms = setparms & ~MASK_ALWAYS_GOOD; if (checkparms & BIT_FIX_INIT) { - return fix_users_list(bdef); + return fix_users_list(); } /* account policy operations */ @@ -973,45 +1151,49 @@ int main (int argc, char **argv) /* import and export operations */ - if ( ((checkparms & BIT_IMPORT) - || (checkparms & BIT_EXPORT)) - && !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER)) ) - { - NTSTATUS status; - - bin = bout = bdef; + if (((checkparms & BIT_IMPORT) || + (checkparms & BIT_EXPORT)) && + !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER))) { if (backend_in) { status = make_pdb_method_name(&bin, backend_in); + } else { + status = make_pdb_method_name(&bin, backend); + } - if ( !NT_STATUS_IS_OK(status) ) { - fprintf(stderr, "Unable to initialize %s.\n", backend_in); - return 1; - } + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, "Unable to initialize %s.\n", + backend_in ? backend_in : backend); + return 1; } if (backend_out) { status = make_pdb_method_name(&bout, backend_out); + } else { + status = make_pdb_method_name(&bout, backend); + } - if ( !NT_STATUS_IS_OK(status) ) { - fprintf(stderr, "Unable to initialize %s.\n", backend_out); - return 1; - } + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, "Unable to initialize %s.\n", + backend_out ? backend_out : backend); + return 1; } if (transfer_account_policies) { - if (!(checkparms & BIT_USER)) + if (!(checkparms & BIT_USER)) { return export_account_policies(bin, bout); + } } else if (transfer_groups) { - if (!(checkparms & BIT_USER)) + if (!(checkparms & BIT_USER)) { return export_groups(bin, bout); + } } else { - return export_database(bin, bout, - (checkparms & BIT_USER) ? user_name : NULL ); + return export_database(bin, bout, + (checkparms & BIT_USER) ? user_name : NULL); } } @@ -1020,7 +1202,7 @@ int main (int argc, char **argv) if ((checkparms & BIT_USER) && !(checkparms & ~BIT_USER)) { checkparms += BIT_LIST; } - + /* modify flag is optional to maintain backwards compatibility */ /* fake up BIT_MODIFY if BIT_USER and at least one of MASK_USER_GOOD is defined */ if (!((checkparms & ~MASK_USER_GOOD) & ~BIT_USER) && (checkparms & MASK_USER_GOOD)) { @@ -1030,13 +1212,13 @@ int main (int argc, char **argv) /* list users operations */ if (checkparms & BIT_LIST) { if (!(checkparms & ~BIT_LIST)) { - return print_users_list (bdef, verbose, spstyle); + return print_users_list(verbose, spstyle); } if (!(checkparms & ~(BIT_USER + BIT_LIST))) { - return print_user_info (bdef, user_name, verbose, spstyle); + return print_user_info(user_name, verbose, spstyle); } } - + /* mask out users options */ checkparms &= ~MASK_USER_GOOD; @@ -1051,7 +1233,7 @@ int main (int argc, char **argv) checkparms |= BIT_MODIFY; checkparms &= ~BIT_LOGONHOURS; } - + /* account operation */ if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) { /* check use of -u option */ @@ -1063,27 +1245,38 @@ int main (int argc, char **argv) /* account creation operations */ if (!(checkparms & ~(BIT_CREATE + BIT_USER + BIT_MACHINE))) { if (checkparms & BIT_MACHINE) { - return new_machine (bdef, user_name); + return new_machine(user_name, machine_sid); } else { - return new_user (bdef, user_name, full_name, home_dir, - home_drive, logon_script, profile_path, user_sid, pw_from_stdin); + return new_user(user_name, full_name, + home_dir, home_drive, + logon_script, profile_path, + user_sid, pw_from_stdin); } } /* account deletion operations */ if (!(checkparms & ~(BIT_DELETE + BIT_USER + BIT_MACHINE))) { if (checkparms & BIT_MACHINE) { - return delete_machine_entry (bdef, user_name); + return delete_machine_entry(user_name); } else { - return delete_user_entry (bdef, user_name); + return delete_user_entry(user_name); } } /* account modification operations */ - if (!(checkparms & ~(BIT_MODIFY + BIT_USER))) { - return set_user_info (bdef, user_name, full_name, home_dir, - acct_desc, home_drive, logon_script, profile_path, account_control, - user_sid, user_domain, badpw_reset, hours_reset); + if (!(checkparms & ~(BIT_MODIFY + BIT_USER + BIT_MACHINE))) { + if (checkparms & BIT_MACHINE) { + return set_machine_info(user_name, + account_control, + machine_sid); + } else { + return set_user_info(user_name, full_name, + home_dir, acct_desc, + home_drive, logon_script, + profile_path, account_control, + user_sid, user_domain, + badpw_reset, hours_reset); + } } } diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 8cca93f5de..c0b2cac18a 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -242,26 +242,29 @@ static NTSTATUS password_change(const char *remote_mach, char *username, char *msg_str = NULL; if (remote_mach != NULL) { - if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER| - LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) { + if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER| + LOCAL_DISABLE_USER|LOCAL_ENABLE_USER| + LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) { /* these things can't be done remotely yet */ + fprintf(stderr, "Invalid remote operation!\n"); return NT_STATUS_UNSUCCESSFUL; } - ret = remote_password_change(remote_mach, username, + ret = remote_password_change(remote_mach, username, old_passwd, new_pw, &err_str); - if (err_str != NULL) - fprintf(stderr, "%s", err_str); - SAFE_FREE(err_str); - return ret; + } else { + ret = local_password_change(username, local_flags, new_pw, + &err_str, &msg_str); } - ret = local_password_change(username, local_flags, new_pw, - &err_str, &msg_str); - - if(msg_str) + if (msg_str) { printf("%s", msg_str); - if(err_str) + } + if (err_str) { fprintf(stderr, "%s", err_str); + } + if (!NT_STATUS_IS_OK(ret) && !err_str) { + fprintf(stderr, "Failed to change password!\n"); + } SAFE_FREE(msg_str); SAFE_FREE(err_str); @@ -430,21 +433,8 @@ static int process_root(int local_flags) } if((local_flags & LOCAL_SET_PASSWORD) && (new_passwd == NULL)) { - struct passwd *passwd; - - if (remote_machine == NULL) { - passwd = getpwnam_alloc(NULL, user_name); - - if (!passwd) { - fprintf(stderr, "Cannot locate Unix account for " - "'%s'!\n", user_name); - exit(1); - } - TALLOC_FREE(passwd); - } new_passwd = prompt_for_new_password(stdin_passwd_get); - if(!new_passwd) { fprintf(stderr, "Unable to get new password.\n"); exit(1); @@ -455,7 +445,6 @@ static int process_root(int local_flags) if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags))) { - fprintf(stderr,"Failed to modify password entry for user %s\n", user_name); result = 1; goto done; } @@ -550,7 +539,6 @@ static int process_nonroot(int local_flags) if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_pw, new_pw, 0))) { - fprintf(stderr,"Failed to change password for %s\n", user_name); result = 1; goto done; } diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c index 58e641b630..879c2e0ecf 100644 --- a/source3/winbindd/idmap_adex/gc_util.c +++ b/source3/winbindd/idmap_adex/gc_util.c @@ -716,11 +716,11 @@ done: *name = NULL; - sid_string = sid_binstring(sid); + sid_string = sid_binstring(frame, sid); BAIL_ON_PTR_ERROR(sid_string, nt_status); filter = talloc_asprintf(frame, "(objectSid=%s)", sid_string); - SAFE_FREE(sid_string); + TALLOC_FREE(sid_string); BAIL_ON_PTR_ERROR(filter, nt_status); nt_status = gc_search_all_forests_unique(filter, &ads, &msg); diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c index f9d73f5f95..00db018de2 100644 --- a/source3/winbindd/idmap_adex/provider_unified.c +++ b/source3/winbindd/idmap_adex/provider_unified.c @@ -483,11 +483,11 @@ static NTSTATUS search_forest(struct likewise_cell *forest_cell, switch (fdata->ftype) { case SidFilter: - sid_binstr = sid_binstring(&fdata->filter.sid); + sid_binstr = sid_binstring(frame, &fdata->filter.sid); BAIL_ON_PTR_ERROR(sid_binstr, nt_status); filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr); - SAFE_FREE(sid_binstr); + TALLOC_FREE(sid_binstr); break; case IdFilter: filter = build_id_filter(fdata->filter.id.id, diff --git a/source4/Makefile b/source4/Makefile index 7bc48b9fe4..2a3ad2def1 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -58,6 +58,7 @@ clustersrcdir := cluster libnetsrcdir := libnet authsrcdir := auth nsswitchsrcdir := ../nsswitch +libwbclientsrcdir := ../nsswitch/libwbclient libsrcdir := lib libsocketsrcdir := lib/socket libcharsetsrcdir := ../lib/util/charset diff --git a/source4/client/smbmnt.c b/source4/client/smbmnt.c deleted file mode 100644 index 0d619a88fe..0000000000 --- a/source4/client/smbmnt.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * smbmnt.c - * - * Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke - * extensively modified by Tridge - * - */ - -#include "includes.h" - -#include <mntent.h> -#include <sys/utsname.h> - -#include <asm/types.h> -#include <asm/posix_types.h> -#include <linux/smb.h> -#include <linux/smb_mount.h> -#include <asm/unistd.h> - -#ifndef MS_MGC_VAL -/* This may look strange but MS_MGC_VAL is what we are looking for and - is what we need from <linux/fs.h> under libc systems and is - provided in standard includes on glibc systems. So... We - switch on what we need... */ -#include <linux/fs.h> -#endif - -static uid_t mount_uid; -static gid_t mount_gid; -static int mount_ro; -static uint_t mount_fmask; -static uint_t mount_dmask; -static int user_mount; -static char *options; - -static void -help(void) -{ - printf("\n"); - printf("Usage: smbmnt mount-point [options]\n"); - printf("Version %s\n\n",VERSION); - printf("-s share share name on server\n" - "-r mount read-only\n" - "-u uid mount as uid\n" - "-g gid mount as gid\n" - "-f mask permission mask for files\n" - "-d mask permission mask for directories\n" - "-o options name=value, list of options\n" - "-h print this help text\n"); -} - -static int -parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share) -{ - int opt; - - while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF) - { - switch (opt) - { - case 's': - *share = optarg; - break; - case 'u': - if (!user_mount) { - mount_uid = strtol(optarg, NULL, 0); - } - break; - case 'g': - if (!user_mount) { - mount_gid = strtol(optarg, NULL, 0); - } - break; - case 'r': - mount_ro = 1; - break; - case 'f': - mount_fmask = strtol(optarg, NULL, 8); - break; - case 'd': - mount_dmask = strtol(optarg, NULL, 8); - break; - case 'o': - options = optarg; - break; - default: - return -1; - } - } - return 0; - -} - -static char * -fullpath(const char *p) -{ - char path[MAXPATHLEN]; - - if (strlen(p) > MAXPATHLEN-1) { - return NULL; - } - - if (realpath(p, path) == NULL) { - fprintf(stderr,"Failed to find real path for mount point\n"); - exit(1); - } - return strdup(path); -} - -/* Check whether user is allowed to mount on the specified mount point. If it's - OK then we change into that directory - this prevents race conditions */ -static int mount_ok(char *mount_point) -{ - struct stat st; - - if (chdir(mount_point) != 0) { - return -1; - } - - if (stat(".", &st) != 0) { - return -1; - } - - if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - return -1; - } - - if ((getuid() != 0) && - ((getuid() != st.st_uid) || - ((st.st_mode & S_IRWXU) != S_IRWXU))) { - errno = EPERM; - return -1; - } - - return 0; -} - -/* Tries to mount using the appropriate format. For 2.2 the struct, - for 2.4 the ascii version. */ -static int -do_mount(char *share_name, uint_t flags, struct smb_mount_data *data) -{ - pstring opts; - struct utsname uts; - char *release, *major, *minor; - char *data1, *data2; - - uname(&uts); - release = uts.release; - major = strtok(release, "."); - minor = strtok(NULL, "."); - if (major && minor && atoi(major) == 2 && atoi(minor) < 4) { - /* < 2.4, assume struct */ - data1 = (char *) data; - data2 = opts; - } else { - /* >= 2.4, assume ascii but fall back on struct */ - data1 = opts; - data2 = (char *) data; - } - - slprintf(opts, sizeof(opts)-1, - "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s", - data->uid, data->gid, data->file_mode, data->dir_mode,options); - if (mount(share_name, ".", "smbfs", flags, data1) == 0) - return 0; - return mount(share_name, ".", "smbfs", flags, data2); -} - - int main(int argc, char *argv[]) -{ - char *mount_point, *share_name = NULL; - FILE *mtab; - int fd; - uint_t flags; - struct smb_mount_data data; - struct mntent ment; - - memset(&data, 0, sizeof(struct smb_mount_data)); - - if (argc < 2) { - help(); - exit(1); - } - - if (argv[1][0] == '-') { - help(); - exit(1); - } - - if (getuid() != 0) { - user_mount = 1; - } - - if (geteuid() != 0) { - fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid()); - exit(1); - } - - mount_uid = getuid(); - mount_gid = getgid(); - mount_fmask = umask(0); - umask(mount_fmask); - mount_fmask = ~mount_fmask; - - mount_point = fullpath(argv[1]); - - argv += 1; - argc -= 1; - - if (mount_ok(mount_point) != 0) { - fprintf(stderr, "cannot mount on %s: %s\n", - mount_point, strerror(errno)); - exit(1); - } - - data.version = SMB_MOUNT_VERSION; - - /* getuid() gives us the real uid, who may umount the fs */ - data.mounted_uid = getuid(); - - if (parse_args(argc, argv, &data, &share_name) != 0) { - help(); - return -1; - } - - data.uid = mount_uid; - data.gid = mount_gid; - data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask; - data.dir_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask; - - if (mount_dmask == 0) { - data.dir_mode = data.file_mode; - if ((data.dir_mode & S_IRUSR) != 0) - data.dir_mode |= S_IXUSR; - if ((data.dir_mode & S_IRGRP) != 0) - data.dir_mode |= S_IXGRP; - if ((data.dir_mode & S_IROTH) != 0) - data.dir_mode |= S_IXOTH; - } - - flags = MS_MGC_VAL; - - if (mount_ro) flags |= MS_RDONLY; - - if (do_mount(share_name, flags, &data) < 0) { - switch (errno) { - case ENODEV: - fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n"); - break; - default: - perror("mount error"); - } - fprintf(stderr, "Please refer to the smbmnt(8) manual page\n"); - return -1; - } - - ment.mnt_fsname = share_name ? share_name : "none"; - ment.mnt_dir = mount_point; - ment.mnt_type = "smbfs"; - ment.mnt_opts = ""; - ment.mnt_freq = 0; - ment.mnt_passno= 0; - - mount_point = ment.mnt_dir; - - if (mount_point == NULL) - { - fprintf(stderr, "Mount point too long\n"); - return -1; - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) - { - fprintf(stderr, "Can't get "MOUNTED"~ lock file"); - return 1; - } - close(fd); - - if ((mtab = setmntent(MOUNTED, "a+")) == NULL) - { - fprintf(stderr, "Can't open " MOUNTED); - return 1; - } - - if (addmntent(mtab, &ment) == 1) - { - fprintf(stderr, "Can't write mount entry"); - return 1; - } - if (fchmod(fileno(mtab), 0644) == -1) - { - fprintf(stderr, "Can't set perms on "MOUNTED); - return 1; - } - endmntent(mtab); - - if (unlink(MOUNTED"~") == -1) - { - fprintf(stderr, "Can't remove "MOUNTED"~"); - return 1; - } - - return 0; -} diff --git a/source4/client/smbmount.c b/source4/client/smbmount.c deleted file mode 100644 index c219a42f3a..0000000000 --- a/source4/client/smbmount.c +++ /dev/null @@ -1,942 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMBFS mount program - Copyright (C) Andrew Tridgell 1999 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "system/passwd.h" - -#include <mntent.h> -#include <asm/types.h> -#include <linux/smb_fs.h> - -#define pstrcpy(d,s) safe_strcpy((d),(s),sizeof(pstring)-1) -#define pstrcat(d,s) safe_strcat((d),(s),sizeof(pstring)-1) - -static pstring credentials; -static pstring my_netbios_name; -static pstring password; -static pstring username; -static pstring workgroup; -static pstring mpoint; -static pstring service; -static pstring options; - -static struct in_addr dest_ip; -static bool have_ip; -static int smb_port = 0; -static bool got_user; -static bool got_pass; -static uid_t mount_uid; -static gid_t mount_gid; -static int mount_ro; -static uint_t mount_fmask; -static uint_t mount_dmask; -static bool use_kerberos; -/* TODO: Add code to detect smbfs version in kernel */ -static bool status32_smbfs = false; - -static void usage(void); - -static void exit_parent(int sig) -{ - /* parent simply exits when child says go... */ - exit(0); -} - -static void daemonize(void) -{ - int j, status; - pid_t child_pid; - - signal( SIGTERM, exit_parent ); - - if ((child_pid = sys_fork()) < 0) { - DEBUG(0,("could not fork\n")); - } - - if (child_pid > 0) { - while( 1 ) { - j = waitpid( child_pid, &status, 0 ); - if( j < 0 ) { - if( EINTR == errno ) { - continue; - } - status = errno; - } - break; - } - - /* If we get here - the child exited with some error status */ - if (WIFSIGNALED(status)) - exit(128 + WTERMSIG(status)); - else - exit(WEXITSTATUS(status)); - } - - signal( SIGTERM, SIG_DFL ); - chdir("/"); -} - -static void close_our_files(int client_fd) -{ - int i; - struct rlimit limits; - - getrlimit(RLIMIT_NOFILE,&limits); - for (i = 0; i< limits.rlim_max; i++) { - if (i == client_fd) - continue; - close(i); - } -} - -static void usr1_handler(int x) -{ - return; -} - - -/***************************************************** -return a connection to a server -*******************************************************/ -static struct smbcli_state *do_connection(const char *the_service, bool unicode, int maxprotocol, - struct smbcli_session_options session_options) -{ - struct smbcli_state *c; - struct nmb_name called, calling; - char *server_n; - struct in_addr ip; - pstring server; - char *share; - - if (the_service[0] != '\\' || the_service[1] != '\\') { - usage(); - exit(1); - } - - pstrcpy(server, the_service+2); - share = strchr_m(server,'\\'); - if (!share) { - usage(); - exit(1); - } - *share = 0; - share++; - - server_n = server; - - make_nmb_name(&calling, my_netbios_name, 0x0); - choose_called_name(&called, server, 0x20); - - again: - zero_ip(&ip); - if (have_ip) ip = dest_ip; - - /* have to open a new connection */ - if (!(c=smbcli_initialise(NULL)) || (smbcli_set_port(c, smb_port) != smb_port) || - !smbcli_connect(c, server_n, &ip)) { - DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n)); - if (c) { - talloc_free(c); - } - return NULL; - } - - /* SPNEGO doesn't work till we get NTSTATUS error support */ - /* But it is REQUIRED for kerberos authentication */ - if(!use_kerberos) c->use_spnego = false; - - /* The kernel doesn't yet know how to sign it's packets */ - c->sign_info.allow_smb_signing = false; - - /* Use kerberos authentication if specified */ - c->use_kerberos = use_kerberos; - - if (!smbcli_session_request(c, &calling, &called)) { - char *p; - DEBUG(0,("%d: session request to %s failed (%s)\n", - sys_getpid(), called.name, smbcli_errstr(c))); - talloc_free(c); - if ((p=strchr_m(called.name, '.'))) { - *p = 0; - goto again; - } - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - return NULL; - } - - DEBUG(4,("%d: session request ok\n", sys_getpid())); - - if (!smbcli_negprot(c, unicode, maxprotocol)) { - DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid())); - talloc_free(c); - return NULL; - } - - if (!got_pass) { - char *pass = getpass("Password: "); - if (pass) { - pstrcpy(password, pass); - } - } - - /* This should be right for current smbfs. Future versions will support - large files as well as unicode and oplocks. */ - if (status32_smbfs) { - c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS | - CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS); - } - else { - c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS | - CAP_NT_FIND | CAP_STATUS32 | - CAP_LEVEL_II_OPLOCKS); - c->force_dos_errors = true; - } - - if (!smbcli_session_setup(c, username, - password, strlen(password), - password, strlen(password), - workgroup, session_options)) { - /* if a password was not supplied then try again with a - null username */ - if (password[0] || !username[0] || - !smbcli_session_setup(c, "", "", 0, "", 0, workgroup, - session_options)) { - DEBUG(0,("%d: session setup failed: %s\n", - sys_getpid(), smbcli_errstr(c))); - talloc_free(c); - return NULL; - } - DEBUG(0,("Anonymous login successful\n")); - } - - DEBUG(4,("%d: session setup ok\n", sys_getpid())); - - if (!smbcli_tconX(c, share, "?????", password, strlen(password)+1)) { - DEBUG(0,("%d: tree connect failed: %s\n", - sys_getpid(), smbcli_errstr(c))); - talloc_free(c); - return NULL; - } - - DEBUG(4,("%d: tconx ok\n", sys_getpid())); - - got_pass = true; - - return c; -} - - -/**************************************************************************** -unmount smbfs (this is a bailout routine to clean up if a reconnect fails) - Code blatently stolen from smbumount.c - -mhw- -****************************************************************************/ -static void smb_umount(const char *mount_point) -{ - int fd; - struct mntent *mnt; - FILE* mtab; - FILE* new_mtab; - - /* Programmers Note: - This routine only gets called to the scene of a disaster - to shoot the survivors... A connection that was working - has now apparently failed. We have an active mount point - (presumably) that we need to dump. If we get errors along - the way - make some noise, but we are already turning out - the lights to exit anyways... - */ - if (umount(mount_point) != 0) { - DEBUG(0,("%d: Could not umount %s: %s\n", - sys_getpid(), mount_point, strerror(errno))); - return; - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { - DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid())); - return; - } - - close(fd); - - if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - DEBUG(0,("%d: Can't open " MOUNTED ": %s\n", - sys_getpid(), strerror(errno))); - return; - } - -#define MOUNTED_TMP MOUNTED".tmp" - - if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { - DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n", - sys_getpid(), strerror(errno))); - endmntent(mtab); - return; - } - - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) != 0) { - addmntent(new_mtab, mnt); - } - } - - endmntent(mtab); - - if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - DEBUG(0,("%d: Error changing mode of %s: %s\n", - sys_getpid(), MOUNTED_TMP, strerror(errno))); - return; - } - - endmntent(new_mtab); - - if (rename(MOUNTED_TMP, MOUNTED) < 0) { - DEBUG(0,("%d: Cannot rename %s to %s: %s\n", - sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno))); - return; - } - - if (unlink(MOUNTED"~") == -1) { - DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid())); - return; - } -} - - -/* - * Call the smbfs ioctl to install a connection socket, - * then wait for a signal to reconnect. Note that we do - * not exit after open_sockets() or send_login() errors, - * as the smbfs mount would then have no way to recover. - */ -static void send_fs_socket(struct loadparm_context *lp_ctx, - const char *the_service, const char *mount_point, struct smbcli_state *c) -{ - int fd, closed = 0, res = 1; - pid_t parentpid = getppid(); - struct smb_conn_opt conn_options; - struct smbcli_session_options session_options; - - lp_smbcli_session_options(lp_ctx, &session_options); - - memset(&conn_options, 0, sizeof(conn_options)); - - while (1) { - if ((fd = open(mount_point, O_RDONLY)) < 0) { - DEBUG(0,("mount.smbfs[%d]: can't open %s\n", - sys_getpid(), mount_point)); - break; - } - - conn_options.fd = c->fd; - conn_options.protocol = c->protocol; - conn_options.case_handling = SMB_CASE_DEFAULT; - conn_options.max_xmit = c->max_xmit; - conn_options.server_uid = c->vuid; - conn_options.tid = c->cnum; - conn_options.secmode = c->sec_mode; - conn_options.rawmode = 0; - conn_options.sesskey = c->sesskey; - conn_options.maxraw = 0; - conn_options.capabilities = c->capabilities; - conn_options.serverzone = c->serverzone/60; - - res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); - if (res != 0) { - DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n", - sys_getpid(), res)); - close(fd); - break; - } - - if (parentpid) { - /* Ok... We are going to kill the parent. Now - is the time to break the process group... */ - setsid(); - /* Send a signal to the parent to terminate */ - kill(parentpid, SIGTERM); - parentpid = 0; - } - - close(fd); - - /* This looks wierd but we are only closing the userspace - side, the connection has already been passed to smbfs and - it has increased the usage count on the socket. - - If we don't do this we will "leak" sockets and memory on - each reconnection we have to make. */ - talloc_free(c); - c = NULL; - - if (!closed) { - /* redirect stdout & stderr since we can't know that - the library functions we use are using DEBUG. */ - if ( (fd = open("/dev/null", O_WRONLY)) < 0) - DEBUG(2,("mount.smbfs: can't open /dev/null\n")); - close_our_files(fd); - if (fd >= 0) { - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - close(fd); - } - - /* here we are no longer interactive */ - set_remote_machine_name("smbmount"); /* sneaky ... */ - setup_logging("mount.smbfs", DEBUG_STDERR); - reopen_logs(); - DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid())); - - closed = 1; - } - - /* Wait for a signal from smbfs ... but don't continue - until we actually get a new connection. */ - while (!c) { - CatchSignal(SIGUSR1, &usr1_handler); - pause(); - DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid())); - c = do_connection(the_service, - lp_unicode(lp_ctx), - lp_cli_maxprotocol(lp_ctx), - session_options); - } - } - - smb_umount(mount_point); - DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid())); - exit(1); -} - - -/** - * Mount a smbfs - **/ -static void init_mount(struct loadparm_context *lp_ctx) -{ - char mount_point[MAXPATHLEN+1]; - pstring tmp; - pstring svc2; - struct smbcli_state *c; - char *args[20]; - int i, status; - struct smbcli_session_options session_options; - - if (realpath(mpoint, mount_point) == NULL) { - fprintf(stderr, "Could not resolve mount point %s\n", mpoint); - return; - } - - lp_smbcli_session_options(lp_ctx, &session_options); - - c = do_connection(service, lp_unicode(lp_ctx), lp_cli_maxprotocol(lp_ctx), - session_options); - if (!c) { - fprintf(stderr,"SMB connection failed\n"); - exit(1); - } - - /* - Set up to return as a daemon child and wait in the parent - until the child say it's ready... - */ - daemonize(); - - pstrcpy(svc2, service); - string_replace(svc2, '\\','/'); - string_replace(svc2, ' ','_'); - - memset(args, 0, sizeof(args[0])*20); - - i=0; - args[i++] = "smbmnt"; - - args[i++] = mount_point; - args[i++] = "-s"; - args[i++] = svc2; - - if (mount_ro) { - args[i++] = "-r"; - } - if (mount_uid) { - slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid); - args[i++] = "-u"; - args[i++] = smb_xstrdup(tmp); - } - if (mount_gid) { - slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid); - args[i++] = "-g"; - args[i++] = smb_xstrdup(tmp); - } - if (mount_fmask) { - slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask); - args[i++] = "-f"; - args[i++] = smb_xstrdup(tmp); - } - if (mount_dmask) { - slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask); - args[i++] = "-d"; - args[i++] = smb_xstrdup(tmp); - } - if (options) { - args[i++] = "-o"; - args[i++] = options; - } - - if (sys_fork() == 0) { - char *smbmnt_path; - - asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR); - - if (file_exist(smbmnt_path)) { - execv(smbmnt_path, args); - fprintf(stderr, - "smbfs/init_mount: execv of %s failed. Error was %s.", - smbmnt_path, strerror(errno)); - } else { - execvp("smbmnt", args); - fprintf(stderr, - "smbfs/init_mount: execv of %s failed. Error was %s.", - "smbmnt", strerror(errno)); - } - free(smbmnt_path); - exit(1); - } - - if (waitpid(-1, &status, 0) == -1) { - fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); - /* FIXME: do some proper error handling */ - exit(1); - } - - if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { - fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); - /* FIXME: do some proper error handling */ - exit(1); - } else if (WIFSIGNALED(status)) { - fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status)); - exit(1); - } - - /* Ok... This is the rubicon for that mount point... At any point - after this, if the connections fail and can not be reconstructed - for any reason, we will have to unmount the mount point. There - is no exit from the next call... - */ - send_fs_socket(lp_ctx, service, mount_point, c); -} - - -/**************************************************************************** -get a password from a a file or file descriptor -exit on failure (from smbclient, move to libsmb or shared .c file?) -****************************************************************************/ -static void get_password_file(void) -{ - int fd = -1; - char *p; - bool close_it = false; - pstring spec; - char pass[128]; - - if ((p = getenv("PASSWD_FD")) != NULL) { - pstrcpy(spec, "descriptor "); - pstrcat(spec, p); - sscanf(p, "%d", &fd); - close_it = false; - } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = open(p, O_RDONLY, 0); - pstrcpy(spec, p); - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - spec, strerror(errno)); - exit(1); - } - close_it = true; - } - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, "empty password\n"); - exit(1); - } - - default: - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, strerror(errno)); - exit(1); - } - } - pstrcpy(password, pass); - if (close_it) - close(fd); -} - -/**************************************************************************** -get username and password from a credentials file -exit on failure (from smbclient, move to libsmb or shared .c file?) -****************************************************************************/ -static void read_credentials_file(char *filename) -{ - FILE *auth; - fstring buf; - uint16_t len = 0; - char *ptr, *val, *param; - - if ((auth=sys_fopen(filename, "r")) == NULL) - { - /* fail if we can't open the credentials file */ - DEBUG(0,("ERROR: Unable to open credentials file!\n")); - exit (-1); - } - - while (!feof(auth)) - { - /* get a line from the file */ - if (!fgets (buf, sizeof(buf), auth)) - continue; - len = strlen(buf); - - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } - if (len == 0) - continue; - - /* break up the line into parameter & value. - will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr (buf, '='))) - continue; - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) - { - pstrcpy(password, val); - got_pass = true; - } - else if (strwicmp("username", param) == 0) { - pstrcpy(username, val); - } - - memset(buf, 0, sizeof(buf)); - } - fclose(auth); -} - - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(void) -{ - printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); - - printf("Version %s\n\n",VERSION); - - printf( -"Options:\n\ - username=<arg> SMB username\n\ - password=<arg> SMB password\n\ - credentials=<filename> file with username/password\n\ - krb use kerberos (active directory)\n\ - netbiosname=<arg> source NetBIOS name\n\ - uid=<arg> mount uid or username\n\ - gid=<arg> mount gid or groupname\n\ - port=<arg> remote SMB port number\n\ - fmask=<arg> file umask\n\ - dmask=<arg> directory umask\n\ - debug=<arg> debug level\n\ - ip=<arg> destination host or IP address\n\ - workgroup=<arg> workgroup on destination\n\ - sockopt=<arg> TCP socket options\n\ - scope=<arg> NetBIOS scope\n\ - iocharset=<arg> Linux charset (iso8859-1, utf8)\n\ - codepage=<arg> server codepage (cp850)\n\ - ttl=<arg> dircache time to live\n\ - guest don't prompt for a password\n\ - ro mount read-only\n\ - rw mount read-write\n\ -\n\ -This command is designed to be run from within /bin/mount by giving\n\ -the option '-t smbfs'. For example:\n\ - mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\ -"); -} - - -/**************************************************************************** - Argument parsing for mount.smbfs interface - mount will call us like this: - mount.smbfs device mountpoint -o <options> - - <options> is never empty, containing at least rw or ro - ****************************************************************************/ -static void parse_mount_smb(int argc, char **argv) -{ - int opt; - char *opts; - char *opteq; - extern char *optarg; - int val; - char *p; - - /* FIXME: This function can silently fail if the arguments are - * not in the expected order. - - > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable) - > requires that one gives "-o" before further options like username=... - > . Without -o, the username=.. setting is *silently* ignored. I've - > spent about an hour trying to find out why I couldn't log in now.. - - */ - - - if (argc < 2 || argv[1][0] == '-') { - usage(); - exit(1); - } - - pstrcpy(service, argv[1]); - pstrcpy(mpoint, argv[2]); - - /* Convert any '/' characters in the service name to - '\' characters */ - string_replace(service, '/','\\'); - argc -= 2; - argv += 2; - - opt = getopt(argc, argv, "o:"); - if(opt != 'o') { - return; - } - - options[0] = 0; - p = options; - - /* - * option parsing from nfsmount.c (util-linux-2.9u) - */ - for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) { - DEBUG(3, ("opts: %s\n", opts)); - if ((opteq = strchr_m(opts, '='))) { - val = atoi(opteq + 1); - *opteq = '\0'; - - if (!strcmp(opts, "username") || - !strcmp(opts, "logon")) { - char *lp; - got_user = true; - pstrcpy(username,opteq+1); - if ((lp=strchr_m(username,'%'))) { - *lp = 0; - pstrcpy(password,lp+1); - got_pass = true; - memset(strchr_m(opteq+1,'%')+1,'X',strlen(password)); - } - if ((lp=strchr_m(username,'/'))) { - *lp = 0; - pstrcpy(workgroup,lp+1); - } - } else if(!strcmp(opts, "passwd") || - !strcmp(opts, "password")) { - pstrcpy(password,opteq+1); - got_pass = true; - memset(opteq+1,'X',strlen(password)); - } else if(!strcmp(opts, "credentials")) { - pstrcpy(credentials,opteq+1); - } else if(!strcmp(opts, "netbiosname")) { - pstrcpy(my_netbios_name,opteq+1); - } else if(!strcmp(opts, "uid")) { - mount_uid = nametouid(opteq+1); - } else if(!strcmp(opts, "gid")) { - mount_gid = nametogid(opteq+1); - } else if(!strcmp(opts, "port")) { - smb_port = val; - } else if(!strcmp(opts, "fmask")) { - mount_fmask = strtol(opteq+1, NULL, 8); - } else if(!strcmp(opts, "dmask")) { - mount_dmask = strtol(opteq+1, NULL, 8); - } else if(!strcmp(opts, "debug")) { - DEBUGLEVEL = val; - } else if(!strcmp(opts, "ip")) { - dest_ip = interpret_addr2(opteq+1); - if (is_zero_ip_v4(dest_ip)) { - fprintf(stderr,"Can't resolve address %s\n", opteq+1); - exit(1); - } - have_ip = true; - } else if(!strcmp(opts, "workgroup")) { - pstrcpy(workgroup,opteq+1); - } else if(!strcmp(opts, "sockopt")) { - lp_set_cmdline("socket options", opteq+1); - } else if(!strcmp(opts, "scope")) { - lp_set_cmdline("netbios scope", opteq+1); - } else { - slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1); - p += strlen(p); - } - } else { - val = 1; - if(!strcmp(opts, "nocaps")) { - fprintf(stderr, "Unhandled option: %s\n", opteq+1); - exit(1); - } else if(!strcmp(opts, "guest")) { - *password = '\0'; - got_pass = true; - } else if(!strcmp(opts, "krb")) { -#ifdef HAVE_KRB5 - - use_kerberos = true; - if(!status32_smbfs) - fprintf(stderr, "Warning: kerberos support will only work for samba servers\n"); -#else - fprintf(stderr,"No kerberos support compiled in\n"); - exit(1); -#endif - } else if(!strcmp(opts, "rw")) { - mount_ro = 0; - } else if(!strcmp(opts, "ro")) { - mount_ro = 1; - } else { - strncpy(p, opts, sizeof(pstring) - (p - options) - 1); - p += strlen(opts); - *p++ = ','; - *p = 0; - } - } - } - - if (!*service) { - usage(); - exit(1); - } - - if (p != options) { - *(p-1) = 0; /* remove trailing , */ - DEBUG(3,("passthrough options '%s'\n", options)); - } -} - -/**************************************************************************** - main program -****************************************************************************/ - int main(int argc,char *argv[]) -{ - extern char *optarg; - extern int optind; - char *p; - struct loadparm_context *lp_ctx; - - DEBUGLEVEL = 1; - - /* here we are interactive, even if run from autofs */ - setup_logging("mount.smbfs",DEBUG_STDERR); - -#if 0 /* JRA - Urban says not needed ? */ - /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default - is to not announce any unicode capabilities as current smbfs does - not support it. */ - p = getenv("CLI_FORCE_ASCII"); - if (p && !strcmp(p, "false")) - unsetenv("CLI_FORCE_ASCII"); - else - setenv("CLI_FORCE_ASCII", "true", 1); -#endif - - if (getenv("USER")) { - pstrcpy(username,getenv("USER")); - - if ((p=strchr_m(username,'%'))) { - *p = 0; - pstrcpy(password,p+1); - got_pass = true; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password)); - } - strupper(username); - } - - if (getenv("PASSWD")) { - pstrcpy(password, getenv("PASSWD")); - got_pass = true; - } - - if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { - get_password_file(); - got_pass = true; - } - - if (*username == 0 && getenv("LOGNAME")) { - pstrcpy(username,getenv("LOGNAME")); - } - - lp_ctx = loadparm_init(talloc_autofree_context()); - - if (!lp_load(lp_ctx, dyn_CONFIGFILE)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", - lp_config_file()); - } - - parse_mount_smb(argc, argv); - - if (use_kerberos && !got_user) { - got_pass = true; - } - - if (*credentials != 0) { - read_credentials_file(credentials); - } - - DEBUG(3,("mount.smbfs started (version %s)\n", VERSION)); - - if (*workgroup == 0) { - pstrcpy(workgroup, lp_workgroup()); - } - - if (!*my_netbios_name) { - pstrcpy(my_netbios_name, myhostname()); - } - strupper(my_netbios_name); - - init_mount(lp_ctx); - return 0; -} diff --git a/source4/client/smbumount.c b/source4/client/smbumount.c deleted file mode 100644 index 9ea3083a6f..0000000000 --- a/source4/client/smbumount.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * smbumount.c - * - * Copyright (C) 1995-1998 by Volker Lendecke - * - */ - -#include "includes.h" - -#include <mntent.h> - -#include <asm/types.h> -#include <asm/posix_types.h> -#include <linux/smb.h> -#include <linux/smb_mount.h> -#include <linux/smb_fs.h> - -/* This is a (hopefully) temporary hack due to the fact that - sizeof( uid_t ) != sizeof( __kernel_uid_t ) under glibc. - This may change in the future and smb.h may get fixed in the - future. In the mean time, it's ugly hack time - get over it. -*/ -#undef SMB_IOC_GETMOUNTUID -#define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_uid_t) - -#ifndef O_NOFOLLOW -#define O_NOFOLLOW 0400000 -#endif - -static void -usage(void) -{ - printf("usage: smbumount mountpoint\n"); -} - -static int -umount_ok(const char *mount_point) -{ - /* we set O_NOFOLLOW to prevent users playing games with symlinks to - umount filesystems they don't own */ - int fid = open(mount_point, O_RDONLY|O_NOFOLLOW, 0); - __kernel_uid_t mount_uid; - - if (fid == -1) { - fprintf(stderr, "Could not open %s: %s\n", - mount_point, strerror(errno)); - return -1; - } - - if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid) != 0) { - fprintf(stderr, "%s probably not smb-filesystem\n", - mount_point); - return -1; - } - - if ((getuid() != 0) - && (mount_uid != getuid())) { - fprintf(stderr, "You are not allowed to umount %s\n", - mount_point); - return -1; - } - - close(fid); - return 0; -} - -/* Make a canonical pathname from PATH. Returns a freshly malloced string. - It is up the *caller* to ensure that the PATH is sensible. i.e. - canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.'' - is not a legal pathname for ``/dev/fd0'' Anything we cannot parse - we return unmodified. */ -static char * -canonicalize (char *path) -{ - char *canonical = malloc (PATH_MAX + 1); - - if (!canonical) { - fprintf(stderr, "Error! Not enough memory!\n"); - return NULL; - } - - if (strlen(path) > PATH_MAX) { - fprintf(stderr, "Mount point string too long\n"); - return NULL; - } - - if (path == NULL) - return NULL; - - if (realpath (path, canonical)) - return canonical; - - strncpy (canonical, path, PATH_MAX); - canonical[PATH_MAX] = '\0'; - return canonical; -} - - -int -main(int argc, char *argv[]) -{ - int fd; - char* mount_point; - struct mntent *mnt; - FILE* mtab; - FILE* new_mtab; - - if (argc != 2) { - usage(); - exit(1); - } - - if (geteuid() != 0) { - fprintf(stderr, "smbumount must be installed suid root\n"); - exit(1); - } - - mount_point = canonicalize(argv[1]); - - if (mount_point == NULL) - { - exit(1); - } - - if (umount_ok(mount_point) != 0) { - exit(1); - } - - if (umount(mount_point) != 0) { - fprintf(stderr, "Could not umount %s: %s\n", - mount_point, strerror(errno)); - exit(1); - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) - { - fprintf(stderr, "Can't get "MOUNTED"~ lock file"); - return 1; - } - close(fd); - - if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED ": %s\n", - strerror(errno)); - return 1; - } - -#define MOUNTED_TMP MOUNTED".tmp" - - if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n", - strerror(errno)); - endmntent(mtab); - return 1; - } - - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) != 0) { - addmntent(new_mtab, mnt); - } - } - - endmntent(mtab); - - if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - fprintf(stderr, "Error changing mode of %s: %s\n", - MOUNTED_TMP, strerror(errno)); - exit(1); - } - - endmntent(new_mtab); - - if (rename(MOUNTED_TMP, MOUNTED) < 0) { - fprintf(stderr, "Cannot rename %s to %s: %s\n", - MOUNTED, MOUNTED_TMP, strerror(errno)); - exit(1); - } - - if (unlink(MOUNTED"~") == -1) - { - fprintf(stderr, "Can't remove "MOUNTED"~"); - return 1; - } - - return 0; -} diff --git a/source4/configure.ac b/source4/configure.ac index 82dd1346da..943a7c4345 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -99,6 +99,7 @@ SMB_INCLUDED_LIB_PKGCONFIG(LIBLDB, ldb = LDB_REQUIRED_VERSION, SMB_INCLUDE_MK(lib/ldb/python.mk) m4_include(lib/tls/config.m4) +m4_include(torture/libnetapi/config.m4) dnl m4_include(auth/kerberos/config.m4) m4_include(auth/gensec/config.m4) diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index a924024160..38858efc7c 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -6,17 +6,17 @@ Copyright (C) Andrew Tridgell 2005 Copyright (C) Volker Lendecke 2004 Copyright (C) Stefan Metzmacher 2004 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -77,20 +77,20 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn, ldapsrv_terminate_connection(conn, "no memory"); return; } - + call->request = talloc_steal(call, msg); call->conn = conn; call->replies = NULL; call->send_callback = NULL; call->send_private = NULL; - + /* make the call */ status = ldapsrv_do_call(call); if (!NT_STATUS_IS_OK(status)) { talloc_free(call); return; } - + blob = data_blob(NULL, 0); if (call->replies == NULL) { @@ -210,7 +210,7 @@ static void ldapsrv_send(struct stream_connection *c, uint16_t flags) { struct ldapsrv_connection *conn = talloc_get_type(c->private_data, struct ldapsrv_connection); - + packet_queue_run(conn->packet); } @@ -294,7 +294,7 @@ static int ldapsrv_load_limits(struct ldapsrv_connection *conn) s = sscanf((const char *)el->values[i].data, "%255[^=]=%d", policy_name, &policy_value); if (ret != 2 || policy_value == 0) continue; - + if (strcasecmp("InitRecvTimeout", policy_name) == 0) { conn->limits.initial_timeout = policy_value; continue; @@ -390,7 +390,7 @@ static void ldapsrv_accept(struct stream_connection *c) if (conn->sockets.tls) { packet_set_unreliable_select(conn->packet); } - + /* Ensure we don't get packets until the database is ready below */ packet_recv_disable(conn->packet); @@ -399,7 +399,7 @@ static void ldapsrv_accept(struct stream_connection *c) stream_terminate_connection(c, "Failed to init server credentials\n"); return; } - + cli_credentials_set_conf(server_credentials, conn->lp_ctx); status = cli_credentials_set_machine_account(server_credentials, conn->lp_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -483,7 +483,7 @@ static NTSTATUS add_socket(struct tevent_context *event_context, if (!ldb) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - + if (samdb_is_gc(ldb)) { port = 3268; status = stream_setup_socket(event_context, lp_ctx, diff --git a/source4/libcli/security/sddl.c b/source4/libcli/security/sddl.c index a8d893f085..39bdf047ac 100644 --- a/source4/libcli/security/sddl.c +++ b/source4/libcli/security/sddl.c @@ -80,11 +80,34 @@ static const struct { { "CO", SID_CREATOR_OWNER }, { "CG", SID_CREATOR_GROUP }, + { "AN", SID_NT_ANONYMOUS }, + { "BG", SID_BUILTIN_GUESTS }, + { "BO", SID_BUILTIN_BACKUP_OPERATORS }, + { "BU", SID_BUILTIN_USERS }, + { "IU", SID_NT_INTERACTIVE }, + { "LS", SID_NT_LOCAL_SERVICE }, + { "NO", SID_BUILTIN_NETWORK_CONF_OPERATORS }, + { "NS", SID_NT_NETWORK_SERVICE }, + { "NU", SID_NT_NETWORK }, + { "PU", SID_BUILTIN_POWER_USERS }, + { "RC", SID_NT_RESTRICTED }, + { "RD", SID_BUILTIN_REMOTE_DESKTOP_USERS }, + { "RE", SID_BUILTIN_REPLICATOR }, + { "SO", SID_BUILTIN_ACCOUNT_OPERATORS }, + { "SU", SID_NT_SERVICE }, + { "DA", NULL, DOMAIN_RID_ADMINS }, { "EA", NULL, DOMAIN_RID_ENTERPRISE_ADMINS }, { "DD", NULL, DOMAIN_RID_DCS }, { "DU", NULL, DOMAIN_RID_USERS }, { "CA", NULL, DOMAIN_RID_CERT_ADMINS }, + + { "DC", NULL, DOMAIN_RID_DOMAIN_MEMBERS }, + { "DG", NULL, DOMAIN_RID_GUESTS }, + { "LA", NULL, DOMAIN_RID_ADMINISTRATOR }, + { "LG", NULL, DOMAIN_RID_GUEST }, + { "PA", NULL, DOMAIN_RID_POLICY_ADMINS }, + { "SA", NULL, DOMAIN_RID_SCHEMA_ADMINS }, }; /* diff --git a/source4/libcli/wbclient/config.mk b/source4/libcli/wbclient/config.mk index 00df5dbb22..af4d3eff82 100644 --- a/source4/libcli/wbclient/config.mk +++ b/source4/libcli/wbclient/config.mk @@ -1,5 +1,5 @@ -[SUBSYSTEM::LIBWBCLIENT] +[SUBSYSTEM::LIBWBCLIENT_OLD] PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBEVENTS PRIVATE_DEPENDENCIES = NDR_WINBIND MESSAGING -LIBWBCLIENT_OBJ_FILES = $(libclisrcdir)/wbclient/wbclient.o +LIBWBCLIENT_OLD_OBJ_FILES = $(libclisrcdir)/wbclient/wbclient.o diff --git a/source4/main.mk b/source4/main.mk index 2e74ba9a5b..b4a82017c8 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -7,6 +7,7 @@ mkinclude smbd/process_model.mk mkinclude libnet/config.mk mkinclude auth/config.mk mkinclude ../nsswitch/config.mk +mkinclude ../nsswitch/libwbclient/config.mk mkinclude lib/samba3/config.mk mkinclude lib/socket/config.mk mkinclude ../lib/util/charset/config.mk diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 1d7949214a..1aaef3f1d4 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -42,7 +42,7 @@ OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = ntvfs_posix_init #PRIVATE_DEPENDENCIES = pvfs_acl_xattr pvfs_acl_nfs4 PRIVATE_DEPENDENCIES = NDR_XATTR WRAP_XATTR BLKID ntvfs_common MESSAGING \ - LIBWBCLIENT pvfs_acl pvfs_aio + LIBWBCLIENT_OLD pvfs_acl pvfs_aio # End MODULE ntvfs_posix ################################################ diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index dfc3d17bed..f3dc074125 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -85,7 +85,7 @@ PRIVATE_DEPENDENCIES = \ SAMDB \ NDR_UNIXINFO \ NSS_WRAPPER \ - LIBWBCLIENT + LIBWBCLIENT_OLD # End MODULE dcerpc_unixinfo ################################################ diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index fabc88d02d..03acf97cab 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -1213,6 +1213,9 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL if (d_state->builtin) { DEBUG(5, ("Cannot create a user in the BUILTIN domain")); return NT_STATUS_ACCESS_DENIED; + } else if (r->in.acct_flags == ACB_DOMTRUST) { + /* Domain trust accounts must be created by the LSA calls */ + return NT_STATUS_ACCESS_DENIED; } account_name = r->in.account_name->string; @@ -1220,6 +1223,11 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_INVALID_PARAMETER; } + /* + * Start a transaction, so we can query and do a subsequent atomic + * modify + */ + ret = ldb_transaction_start(d_state->sam_ctx); if (ret != 0) { DEBUG(0,("Failed to start a transaction for user creation: %s\n", @@ -1258,6 +1266,7 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL } else if (r->in.acct_flags == ACB_WSTRUST) { if (cn_name[cn_name_len - 1] != '$') { + ldb_transaction_cancel(d_state->sam_ctx); return NT_STATUS_FOOBAR; } cn_name[cn_name_len - 1] = '\0'; @@ -1267,17 +1276,13 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL } else if (r->in.acct_flags == ACB_SVRTRUST) { if (cn_name[cn_name_len - 1] != '$') { + ldb_transaction_cancel(d_state->sam_ctx); return NT_STATUS_FOOBAR; } cn_name[cn_name_len - 1] = '\0'; container = "OU=Domain Controllers"; obj_class = "computer"; samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS); - - } else if (r->in.acct_flags == ACB_DOMTRUST) { - container = "CN=Users"; - obj_class = "user"; - } else { ldb_transaction_cancel(d_state->sam_ctx); return NT_STATUS_INVALID_PARAMETER; @@ -1292,9 +1297,7 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name); samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class); - - /* Start a transaction, so we can query and do a subsequent atomic modify */ - + /* create the user */ ret = ldb_add(d_state->sam_ctx, msg); switch (ret) { diff --git a/source4/selftest/tests.sh b/source4/selftest/tests.sh index 79199bc2c0..58cdc0898b 100755 --- a/source4/selftest/tests.sh +++ b/source4/selftest/tests.sh @@ -117,7 +117,7 @@ plantest "ldb" none TEST_DATA_PREFIX=\$PREFIX $LDBDIR/tests/test-tdb.sh ncacn_np_tests="RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-HANDLES RPC-SAMSYNC RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME RPC-SAMBA3-LSA RPC-BINDSAMBA3 RPC-NETLOGSAMBA3 RPC-ASYNCBIND RPC-LSALOOKUP RPC-LSA-GETUSER RPC-SCHANNEL2 RPC-AUTHCONTEXT" ncalrpc_tests="RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-DRSUAPI RPC-ASYNCBIND RPC-LSALOOKUP RPC-LSA-GETUSER RPC-SCHANNEL2 RPC-AUTHCONTEXT" ncacn_ip_tcp_tests="RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-HANDLES RPC-DSSYNC RPC-ASYNCBIND RPC-LSALOOKUP RPC-LSA-GETUSER RPC-SCHANNEL2 RPC-AUTHCONTEXT RPC-OBJECTUUID" -slow_ncacn_np_tests="RPC-SAMLOGON RPC-SAMR RPC-SAMR-USERS RPC-SAMR-PASSWORDS" +slow_ncacn_np_tests="RPC-SAMLOGON RPC-SAMR RPC-SAMR-USERS RPC-SAMR-USERS-PRIVILEGES RPC-SAMR-PASSWORDS RPC-SAMR-PASSWORDS-PWDLASTSET" slow_ncalrpc_tests="RPC-SAMR RPC-SAMR-PASSWORDS" slow_ncacn_ip_tcp_tests="RPC-SAMR RPC-SAMR-PASSWORDS RPC-CRACKNAMES" diff --git a/source4/setup/provision_configuration.ldif b/source4/setup/provision_configuration.ldif index 63b807ba4a..fff380505f 100644 --- a/source4/setup/provision_configuration.ldif +++ b/source4/setup/provision_configuration.ldif @@ -96,21 +96,15 @@ dn: CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: container cn: Extended-Rights -instanceType: 4 -showInAdvancedViewOnly: TRUE systemFlags: -2147483648 -objectCategory: CN=Container,CN=Schema,${CONFIGDN} dn: CN=Change-Rid-Master,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Change-Rid-Master -instanceType: 4 displayName: Change Rid Master -showInAdvancedViewOnly: TRUE rightsGuid: d58d5f36-0a98-11d1-adbb-00c04fd8d5cd appliesTo: 6617188d-8f3c-11d0-afda-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 29 validAccesses: 256 @@ -118,12 +112,9 @@ dn: CN=Do-Garbage-Collection,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Do-Garbage-Collection -instanceType: 4 displayName: Do Garbage Collection -showInAdvancedViewOnly: TRUE rightsGuid: fec364e0-0a98-11d1-adbb-00c04fd8d5cd appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 31 validAccesses: 256 @@ -131,12 +122,9 @@ dn: CN=Recalculate-Hierarchy,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Recalculate-Hierarchy -instanceType: 4 displayName: Recalculate Hierarchy -showInAdvancedViewOnly: TRUE rightsGuid: 0bc1554e-0a99-11d1-adbb-00c04fd8d5cd appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 32 validAccesses: 256 @@ -144,12 +132,9 @@ dn: CN=Allocate-Rids,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Allocate-Rids -instanceType: 4 displayName: Allocate Rids -showInAdvancedViewOnly: TRUE rightsGuid: 1abd7cf8-0a99-11d1-adbb-00c04fd8d5cd appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 33 validAccesses: 256 @@ -157,12 +142,9 @@ dn: CN=Change-PDC,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Change-PDC -instanceType: 4 displayName: Change PDC -showInAdvancedViewOnly: TRUE rightsGuid: bae50096-4752-11d1-9052-00c04fc2d4cf appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 34 validAccesses: 256 @@ -170,12 +152,9 @@ dn: CN=Add-GUID,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Add-GUID -instanceType: 4 displayName: Add GUID -showInAdvancedViewOnly: TRUE rightsGuid: 440820ad-65b4-11d1-a3da-0000f875ae0d appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 35 validAccesses: 256 @@ -183,12 +162,9 @@ dn: CN=Change-Domain-Master,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Change-Domain-Master -instanceType: 4 displayName: Change Domain Master -showInAdvancedViewOnly: TRUE rightsGuid: 014bf69c-7b3b-11d1-85f6-08002be74fab appliesTo: ef9e60e0-56f7-11d1-a9c6-0000f80367c1 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 36 validAccesses: 256 @@ -196,14 +172,11 @@ dn: CN=Public-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Public-Information -instanceType: 4 displayName: Public Information -showInAdvancedViewOnly: TRUE rightsGuid: e48d0154-bcf8-11d1-8702-00c04fb96050 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 37 validAccesses: 48 @@ -211,12 +184,9 @@ dn: CN=msmq-Receive-Dead-Letter,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Receive-Dead-Letter -instanceType: 4 displayName: Receive Dead Letter -showInAdvancedViewOnly: TRUE rightsGuid: 4b6e08c0-df3c-11d1-9c86-006008764d0e appliesTo: 9a0dc344-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 38 validAccesses: 256 @@ -224,12 +194,9 @@ dn: CN=msmq-Peek-Dead-Letter,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Peek-Dead-Letter -instanceType: 4 displayName: Peek Dead Letter -showInAdvancedViewOnly: TRUE rightsGuid: 4b6e08c1-df3c-11d1-9c86-006008764d0e appliesTo: 9a0dc344-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 39 validAccesses: 256 @@ -237,12 +204,9 @@ dn: CN=msmq-Receive-computer-Journal,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Receive-computer-Journal -instanceType: 4 displayName: Receive Computer Journal -showInAdvancedViewOnly: TRUE rightsGuid: 4b6e08c2-df3c-11d1-9c86-006008764d0e appliesTo: 9a0dc344-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 40 validAccesses: 256 @@ -250,12 +214,9 @@ dn: CN=msmq-Peek-computer-Journal,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Peek-computer-Journal -instanceType: 4 displayName: Peek Computer Journal -showInAdvancedViewOnly: TRUE rightsGuid: 4b6e08c3-df3c-11d1-9c86-006008764d0e appliesTo: 9a0dc344-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 41 validAccesses: 256 @@ -263,12 +224,9 @@ dn: CN=msmq-Receive,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Receive -instanceType: 4 displayName: Receive Message -showInAdvancedViewOnly: TRUE rightsGuid: 06bd3200-df3e-11d1-9c86-006008764d0e appliesTo: 9a0dc343-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 42 validAccesses: 256 @@ -276,12 +234,9 @@ dn: CN=msmq-Peek,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Peek -instanceType: 4 displayName: Peek Message -showInAdvancedViewOnly: TRUE rightsGuid: 06bd3201-df3e-11d1-9c86-006008764d0e appliesTo: 9a0dc343-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 43 validAccesses: 256 @@ -289,13 +244,10 @@ dn: CN=msmq-Send,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Send -instanceType: 4 displayName: Send Message -showInAdvancedViewOnly: TRUE rightsGuid: 06bd3202-df3e-11d1-9c86-006008764d0e appliesTo: 46b27aac-aafa-4ffb-b773-e5bf621ee87b appliesTo: 9a0dc343-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 44 validAccesses: 256 @@ -303,12 +255,9 @@ dn: CN=msmq-Receive-journal,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Receive-journal -instanceType: 4 displayName: Receive Journal -showInAdvancedViewOnly: TRUE rightsGuid: 06bd3203-df3e-11d1-9c86-006008764d0e appliesTo: 9a0dc343-c100-11d1-bbc5-0080c76670c0 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 45 validAccesses: 256 @@ -316,12 +265,9 @@ dn: CN=msmq-Open-Connector,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: msmq-Open-Connector -instanceType: 4 displayName: Open Connector Queue -showInAdvancedViewOnly: TRUE rightsGuid: b4e60130-df3f-11d1-9c86-006008764d0e appliesTo: bf967ab3-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 46 validAccesses: 256 @@ -329,12 +275,9 @@ dn: CN=Apply-Group-Policy,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Apply-Group-Policy -instanceType: 4 displayName: Apply Group Policy -showInAdvancedViewOnly: TRUE rightsGuid: edacfd8f-ffb3-11d1-b41d-00a0c968f939 appliesTo: f30e3bc2-9ff0-11d1-b603-0000f80367c1 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 47 validAccesses: 256 @@ -342,13 +285,10 @@ dn: CN=RAS-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: RAS-Information -instanceType: 4 displayName: Remote Access Information -showInAdvancedViewOnly: TRUE rightsGuid: 037088f8-0ae1-11d2-b422-00a0c968f939 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 48 validAccesses: 48 @@ -356,12 +296,9 @@ dn: CN=DS-Install-Replica,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Install-Replica -instanceType: 4 displayName: Add/Remove Replica In Domain -showInAdvancedViewOnly: TRUE rightsGuid: 9923a32a-3607-11d2-b9be-0000f87a36b2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 49 validAccesses: 256 @@ -369,12 +306,9 @@ dn: CN=Change-Infrastructure-Master,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Change-Infrastructure-Master -instanceType: 4 displayName: Change Infrastructure Master -showInAdvancedViewOnly: TRUE rightsGuid: cc17b1fb-33d9-11d2-97d4-00c04fd8d5cd appliesTo: 2df90d89-009f-11d2-aa4c-00c04fd7d83a -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 50 validAccesses: 256 @@ -382,12 +316,9 @@ dn: CN=Update-Schema-Cache,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Update-Schema-Cache -instanceType: 4 displayName: Update Schema Cache -showInAdvancedViewOnly: TRUE rightsGuid: be2bb760-7f46-11d2-b9ad-00c04f79f805 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 51 validAccesses: 256 @@ -395,12 +326,9 @@ dn: CN=Recalculate-Security-Inheritance,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Recalculate-Security-Inheritance -instanceType: 4 displayName: Recalculate Security Inheritance -showInAdvancedViewOnly: TRUE rightsGuid: 62dd28a8-7f46-11d2-b9ad-00c04f79f805 appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 52 validAccesses: 256 @@ -408,12 +336,9 @@ dn: CN=DS-Check-Stale-Phantoms,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Check-Stale-Phantoms -instanceType: 4 displayName: Check Stale Phantoms -showInAdvancedViewOnly: TRUE rightsGuid: 69ae6200-7f46-11d2-b9ad-00c04f79f805 appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 53 validAccesses: 256 @@ -421,12 +346,9 @@ dn: CN=Certificate-Enrollment,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Certificate-Enrollment -instanceType: 4 displayName: Enroll -showInAdvancedViewOnly: TRUE rightsGuid: 0e10c968-78fb-11d2-90d4-00c04f79dc55 appliesTo: e5209ca2-3bba-11d2-90cc-00c04fd91ab1 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 54 validAccesses: 256 @@ -434,12 +356,9 @@ dn: CN=Self-Membership,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Self-Membership -instanceType: 4 displayName: Add/Remove self as member -showInAdvancedViewOnly: TRUE rightsGuid: bf9679c0-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a9c-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 12 validAccesses: 8 @@ -447,12 +366,9 @@ dn: CN=Validated-DNS-Host-Name,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Validated-DNS-Host-Name -instanceType: 4 displayName: Validated write to DNS host name -showInAdvancedViewOnly: TRUE rightsGuid: 72e39547-7b18-11d1-adef-00c04fd8d5cd appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 13 validAccesses: 8 @@ -460,12 +376,9 @@ dn: CN=Validated-SPN,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Validated-SPN -instanceType: 4 displayName: Validated write to service principal name -showInAdvancedViewOnly: TRUE rightsGuid: f3a64788-5306-11d1-a9c5-0000f80367c1 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 14 validAccesses: 8 @@ -473,13 +386,10 @@ dn: CN=Generate-RSoP-Planning,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Generate-RSoP-Planning -instanceType: 4 displayName: Generate Resultant Set of Policy (Planning) -showInAdvancedViewOnly: TRUE rightsGuid: b7b1b3dd-ab09-4242-9e30-9980e5d322f7 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 appliesTo: bf967aa5-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 55 validAccesses: 256 @@ -487,12 +397,9 @@ dn: CN=Refresh-Group-Cache,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Refresh-Group-Cache -instanceType: 4 displayName: Refresh Group Cache for Logons -showInAdvancedViewOnly: TRUE rightsGuid: 9432c620-033c-4db7-8b58-14ef6d0bf477 appliesTo: f0f8ffab-1191-11d0-a060-00aa006c33ed -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 56 validAccesses: 256 @@ -500,12 +407,9 @@ dn: CN=SAM-Enumerate-Entire-Domain,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: SAM-Enumerate-Entire-Domain -instanceType: 4 displayName: Enumerate Entire SAM Domain -showInAdvancedViewOnly: TRUE rightsGuid: 91d67418-0135-4acc-8d79-c08e857cfbec appliesTo: bf967aad-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 57 validAccesses: 256 @@ -513,13 +417,10 @@ dn: CN=Generate-RSoP-Logging,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Generate-RSoP-Logging -instanceType: 4 displayName: Generate Resultant Set of Policy (Logging) -showInAdvancedViewOnly: TRUE rightsGuid: b7b1b3de-ab09-4242-9e30-9980e5d322f7 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 appliesTo: bf967aa5-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 58 validAccesses: 256 @@ -527,12 +428,9 @@ dn: CN=Domain-Other-Parameters,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Domain-Other-Parameters -instanceType: 4 displayName: Other Domain Parameters (for use by SAM) -showInAdvancedViewOnly: TRUE rightsGuid: b8119fd0-04f6-4762-ab7a-4986c76b3f9a appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 59 validAccesses: 48 @@ -540,12 +438,9 @@ dn: CN=DNS-Host-Name-Attributes,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DNS-Host-Name-Attributes -instanceType: 4 displayName: DNS Host Name Attributes -showInAdvancedViewOnly: TRUE rightsGuid: 72e39547-7b18-11d1-adef-00c04fd8d5cd appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 60 validAccesses: 48 @@ -553,12 +448,9 @@ dn: CN=Create-Inbound-Forest-Trust,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Create-Inbound-Forest-Trust -instanceType: 4 displayName: Create Inbound Forest Trust -showInAdvancedViewOnly: TRUE rightsGuid: e2a36dc9-ae17-47c3-b58b-be34c55ba633 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 61 validAccesses: 256 @@ -566,14 +458,11 @@ dn: CN=DS-Replication-Get-Changes-All,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Replication-Get-Changes-All -instanceType: 4 displayName: Replicating Directory Changes All -showInAdvancedViewOnly: TRUE rightsGuid: 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 62 validAccesses: 256 @@ -581,12 +470,9 @@ dn: CN=Migrate-SID-History,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Migrate-SID-History -instanceType: 4 displayName: Migrate SID History -showInAdvancedViewOnly: TRUE rightsGuid: BA33815A-4F93-4c76-87F3-57574BFF8109 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 63 validAccesses: 256 @@ -594,14 +480,11 @@ dn: CN=Reanimate-Tombstones,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Reanimate-Tombstones -instanceType: 4 displayName: Reanimate Tombstones -showInAdvancedViewOnly: TRUE rightsGuid: 45EC5156-DB7E-47bb-B53F-DBEB2D03C40F appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 64 validAccesses: 256 @@ -609,14 +492,11 @@ dn: CN=Allowed-To-Authenticate,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Allowed-To-Authenticate -instanceType: 4 displayName: Allowed to Authenticate -showInAdvancedViewOnly: TRUE rightsGuid: 68B1D179-0D15-4d4f-AB71-46152E79A7BC appliesTo: 4828cc14-1437-45bc-9b07-ad6f015e5f28 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 65 validAccesses: 256 @@ -624,12 +504,9 @@ dn: CN=DS-Execute-Intentions-Script,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Execute-Intentions-Script -instanceType: 4 displayName: Execute Forest Update Script -showInAdvancedViewOnly: TRUE rightsGuid: 2f16c4a5-b98e-432c-952a-cb388ba33f2e appliesTo: ef9e60e0-56f7-11d1-a9c6-0000f80367c1 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 66 validAccesses: 256 @@ -637,14 +514,11 @@ dn: CN=DS-Replication-Monitor-Topology,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Replication-Monitor-Topology -instanceType: 4 displayName: Monitor Active Directory Replication -showInAdvancedViewOnly: TRUE rightsGuid: f98340fb-7c5b-4cdb-a00b-2ebdfa115a96 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 67 validAccesses: 256 @@ -652,12 +526,9 @@ dn: CN=Update-Password-Not-Required-Bit,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Update-Password-Not-Required-Bit -instanceType: 4 displayName: Update Password Not Required Bit -showInAdvancedViewOnly: TRUE rightsGuid: 280f369c-67c7-438e-ae98-1d46f3c6f541 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 68 validAccesses: 256 @@ -665,12 +536,9 @@ dn: CN=Unexpire-Password,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Unexpire-Password -instanceType: 4 displayName: Unexpire Password -showInAdvancedViewOnly: TRUE rightsGuid: ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 69 validAccesses: 256 @@ -678,12 +546,9 @@ dn: CN=Enable-Per-User-Reversibly-Encrypted-Password,CN=Extended-Rights,${CONFIG objectClass: top objectClass: controlAccessRight cn: Enable-Per-User-Reversibly-Encrypted-Password -instanceType: 4 displayName: Enable Per User Reversibly Encrypted Password -showInAdvancedViewOnly: TRUE rightsGuid: 05c74c5e-4deb-43b4-bd9f-86664c2a7fd5 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 70 validAccesses: 256 @@ -691,12 +556,9 @@ dn: CN=DS-Query-Self-Quota,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Query-Self-Quota -instanceType: 4 displayName: Query Self Quota -showInAdvancedViewOnly: TRUE rightsGuid: 4ecc03fe-ffc0-4947-b630-eb672a8a9dbc appliesTo: da83fc4f-076f-4aea-b4dc-8f4dab9b5993 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 71 validAccesses: 256 @@ -704,12 +566,9 @@ dn: CN=Domain-Administer-Server,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Domain-Administer-Server -instanceType: 4 displayName: Domain Administer Server -showInAdvancedViewOnly: TRUE rightsGuid: ab721a52-1e2f-11d0-9819-00aa0040529b appliesTo: bf967aad-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 1 validAccesses: 256 @@ -717,14 +576,11 @@ dn: CN=User-Change-Password,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: User-Change-Password -instanceType: 4 displayName: Change Password -showInAdvancedViewOnly: TRUE rightsGuid: ab721a53-1e2f-11d0-9819-00aa0040529b appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 2 validAccesses: 256 @@ -732,14 +588,11 @@ dn: CN=User-Force-Change-Password,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: User-Force-Change-Password -instanceType: 4 displayName: Reset Password -showInAdvancedViewOnly: TRUE rightsGuid: 00299570-246d-11d0-a768-00aa006e0529 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 3 validAccesses: 256 @@ -747,14 +600,11 @@ dn: CN=Send-As,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Send-As -instanceType: 4 displayName: Send As -showInAdvancedViewOnly: TRUE rightsGuid: ab721a54-1e2f-11d0-9819-00aa0040529b appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 4 validAccesses: 256 @@ -762,14 +612,11 @@ dn: CN=Receive-As,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Receive-As -instanceType: 4 displayName: Receive As -showInAdvancedViewOnly: TRUE rightsGuid: ab721a56-1e2f-11d0-9819-00aa0040529b appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 5 validAccesses: 256 @@ -777,12 +624,9 @@ dn: CN=Send-To,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Send-To -instanceType: 4 displayName: Send To -showInAdvancedViewOnly: TRUE rightsGuid: ab721a55-1e2f-11d0-9819-00aa0040529b appliesTo: bf967a9c-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 6 validAccesses: 256 @@ -790,13 +634,10 @@ dn: CN=Domain-Password,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Domain-Password -instanceType: 4 displayName: Domain Password & Lockout Policies -showInAdvancedViewOnly: TRUE rightsGuid: c7407360-20bf-11d0-a768-00aa006e0529 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 appliesTo: 19195a5a-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 7 validAccesses: 48 @@ -804,13 +645,10 @@ dn: CN=General-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: General-Information -instanceType: 4 displayName: General Information -showInAdvancedViewOnly: TRUE rightsGuid: 59ba2f42-79a2-11d0-9020-00c04fc2d3cf appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 8 validAccesses: 48 @@ -818,14 +656,11 @@ dn: CN=User-Account-Restrictions,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: User-Account-Restrictions -instanceType: 4 displayName: Account Restrictions -showInAdvancedViewOnly: TRUE rightsGuid: 4c164200-20c0-11d0-a768-00aa006e0529 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 9 validAccesses: 48 @@ -833,13 +668,10 @@ dn: CN=User-Logon,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: User-Logon -instanceType: 4 displayName: Logon Information -showInAdvancedViewOnly: TRUE rightsGuid: 5f202010-79a5-11d0-9020-00c04fc2d4cf appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 10 validAccesses: 48 @@ -847,13 +679,10 @@ dn: CN=Membership,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Membership -instanceType: 4 displayName: Group Membership -showInAdvancedViewOnly: TRUE rightsGuid: bc0ac240-79a9-11d0-9020-00c04fc2d4cf appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 11 validAccesses: 48 @@ -861,12 +690,9 @@ dn: CN=Open-Address-Book,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Open-Address-Book -instanceType: 4 displayName: Open Address List -showInAdvancedViewOnly: TRUE rightsGuid: a1990816-4298-11d1-ade2-00c04fd8d5cd appliesTo: 3e74f60f-3e73-11d1-a9c0-0000f80367c1 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 21 validAccesses: 256 @@ -874,15 +700,12 @@ dn: CN=Personal-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Personal-Information -instanceType: 4 displayName: Personal Information -showInAdvancedViewOnly: TRUE rightsGuid: 77B5B886-944A-11d1-AEBD-0000F80367C1 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a86-0de6-11d0-a285-00aa003049e2 appliesTo: 5cb41ed0-0e4c-11d0-a286-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 23 validAccesses: 48 @@ -890,14 +713,11 @@ dn: CN=Email-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Email-Information -instanceType: 4 displayName: Phone and Mail Options -showInAdvancedViewOnly: TRUE rightsGuid: E45795B2-9455-11d1-AEBD-0000F80367C1 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: bf967a9c-0de6-11d0-a285-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 22 validAccesses: 48 @@ -905,14 +725,11 @@ dn: CN=Web-Information,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Web-Information -instanceType: 4 displayName: Web Information -showInAdvancedViewOnly: TRUE rightsGuid: E45795B3-9455-11d1-AEBD-0000F80367C1 appliesTo: 4828CC14-1437-45bc-9B07-AD6F015E5F28 appliesTo: 5cb41ed0-0e4c-11d0-a286-00aa003049e2 appliesTo: bf967aba-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 24 validAccesses: 48 @@ -920,14 +737,11 @@ dn: CN=DS-Replication-Get-Changes,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Replication-Get-Changes -instanceType: 4 displayName: Replicating Directory Changes -showInAdvancedViewOnly: TRUE rightsGuid: 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 25 validAccesses: 256 @@ -935,14 +749,11 @@ dn: CN=DS-Replication-Synchronize,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Replication-Synchronize -instanceType: 4 displayName: Replication Synchronization -showInAdvancedViewOnly: TRUE rightsGuid: 1131f6ab-9c07-11d1-f79f-00c04fc2dcd2 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 26 validAccesses: 256 @@ -950,14 +761,11 @@ dn: CN=DS-Replication-Manage-Topology,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: DS-Replication-Manage-Topology -instanceType: 4 displayName: Manage Replication Topology -showInAdvancedViewOnly: TRUE rightsGuid: 1131f6ac-9c07-11d1-f79f-00c04fc2dcd2 appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 appliesTo: bf967a87-0de6-11d0-a285-00aa003049e2 appliesTo: 19195a5b-6da0-11d0-afd3-00c04fd930c9 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 27 validAccesses: 256 @@ -965,11 +773,8 @@ dn: CN=Change-Schema-Master,CN=Extended-Rights,${CONFIGDN} objectClass: top objectClass: controlAccessRight cn: Change-Schema-Master -instanceType: 4 displayName: Change Schema Master -showInAdvancedViewOnly: TRUE rightsGuid: e12b56b6-0a95-11d1-adbb-00c04fd8d5cd appliesTo: bf967a8f-0de6-11d0-a285-00aa003049e2 -objectCategory: CN=Control-Access-Right,CN=Schema,${CONFIGDN} localizationDisplayId: 28 validAccesses: 256 diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 72747a7886..dd1d5ea817 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -89,6 +89,7 @@ $(eval $(call proto_header_template,$(torturesrcdir)/raw/proto.h,$(TORTURE_RAW_O mkinclude smb2/config.mk mkinclude winbind/config.mk +mkinclude libnetapi/config.mk [SUBSYSTEM::TORTURE_NDR] PRIVATE_DEPENDENCIES = torture SERVICE_SMB diff --git a/source4/torture/libnetapi/config.m4 b/source4/torture/libnetapi/config.m4 new file mode 100644 index 0000000000..43724908ca --- /dev/null +++ b/source4/torture/libnetapi/config.m4 @@ -0,0 +1,28 @@ +############################### +# start SMB_EXT_LIB_NETAPI +# check for netapi.h and -lnetapi + +use_netapi=auto +AC_ARG_ENABLE(netapi, +AS_HELP_STRING([--enable-netapi],[Turn on netapi support (default=yes)]), + [if test x$enable_netapi = xno; then + use_netapi=no + fi]) + + +#if test x$use_netapi = xauto && pkg-config --exists netapi; then +# SMB_EXT_LIB_FROM_PKGCONFIG(NETAPI, netapi < 0.1, +# [use_netapi=yes], +# [use_netapi=no]) +#fi + +if test x$use_netapi = xauto; then + AC_CHECK_HEADERS(netapi.h) + AC_CHECK_LIB_EXT(netapi, NETAPI_LIBS, libnetapi_init) + if test x"$ac_cv_header_netapi_h" = x"yes" -a x"$ac_cv_lib_ext_netapi_libnetapi_init" = x"yes";then + SMB_ENABLE(NETAPI,YES) + else + SMB_ENABLE(TORTURE_LIBNETAPI,NO) + fi + SMB_EXT_LIB(NETAPI, $NETAPI_LIBS) +fi diff --git a/source4/torture/libnetapi/config.mk b/source4/torture/libnetapi/config.mk new file mode 100644 index 0000000000..2ac506e1b2 --- /dev/null +++ b/source4/torture/libnetapi/config.mk @@ -0,0 +1,17 @@ +################################# +# Start SUBSYSTEM TORTURE_LIBNETAPI +[MODULE::TORTURE_LIBNETAPI] +SUBSYSTEM = smbtorture +OUTPUT_TYPE = MERGED_OBJ +INIT_FUNCTION = torture_libnetapi_init +PRIVATE_DEPENDENCIES = \ + POPT_CREDENTIALS \ + NETAPI +# End SUBSYSTEM TORTURE_LIBNETAPI +################################# + +TORTURE_LIBNETAPI_OBJ_FILES = $(addprefix $(torturesrcdir)/libnetapi/, libnetapi.o \ + libnetapi_user.o \ + libnetapi_group.o) + +$(eval $(call proto_header_template,$(torturesrcdir)/libnetapi/proto.h,$(TORTURE_LIBNETAPI_OBJ_FILES:.o=.c))) diff --git a/source4/torture/libnetapi/libnetapi.c b/source4/torture/libnetapi/libnetapi.c new file mode 100644 index 0000000000..c3a27eba0c --- /dev/null +++ b/source4/torture/libnetapi/libnetapi.c @@ -0,0 +1,80 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/smbtorture.h" +#include "auth/credentials/credentials.h" +#include "lib/cmdline/popt_common.h" +#include <netapi.h> +#include "torture/libnetapi/proto.h" + +bool torture_libnetapi_init_context(struct torture_context *tctx, + struct libnetapi_ctx **ctx_p) +{ + NET_API_STATUS status; + struct libnetapi_ctx *ctx; + + status = libnetapi_init(&ctx); + if (status != 0) { + return false; + } + + libnetapi_set_debuglevel(ctx, + talloc_asprintf(ctx, "%d", DEBUGLEVEL)); + libnetapi_set_username(ctx, + cli_credentials_get_username(cmdline_credentials)); + libnetapi_set_password(ctx, + cli_credentials_get_password(cmdline_credentials)); + + *ctx_p = ctx; + + return true; +} + +static bool torture_libnetapi_initialize(struct torture_context *tctx) +{ + NET_API_STATUS status; + struct libnetapi_ctx *ctx; + + status = libnetapi_init(&ctx); + if (status != 0) { + return false; + } + + libnetapi_free(ctx); + + return true; +} + +NTSTATUS torture_libnetapi_init(void) +{ + struct torture_suite *suite; + + suite = torture_suite_create(talloc_autofree_context(), "NETAPI"); + + torture_suite_add_simple_test(suite, "GROUP", torture_libnetapi_group); + torture_suite_add_simple_test(suite, "USER", torture_libnetapi_user); + torture_suite_add_simple_test(suite, "INITIALIZE", torture_libnetapi_initialize); + + suite->description = talloc_strdup(suite, "libnetapi convenience interface tests"); + + torture_register_suite(suite); + + return NT_STATUS_OK; +} diff --git a/source4/torture/libnetapi/libnetapi_group.c b/source4/torture/libnetapi/libnetapi_group.c new file mode 100644 index 0000000000..e8e5ad931a --- /dev/null +++ b/source4/torture/libnetapi/libnetapi_group.c @@ -0,0 +1,520 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/smbtorture.h" +#include <netapi.h> +#include "torture/libnetapi/proto.h" + +#define TORTURE_TEST_USER "testuser" + +#define NETAPI_STATUS(tctx, x,y,fn) \ + torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d)\n", \ + __LINE__, fn, libnetapi_get_error_string(x,y), y); + +#define NETAPI_STATUS_MSG(tctx, x,y,fn,z) \ + torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d), %s\n", \ + __LINE__, fn, libnetapi_get_error_string(x,y), y, z); + +static NET_API_STATUS test_netgroupenum(struct torture_context *tctx, + const char *hostname, + uint32_t level, + const char *groupname) +{ + NET_API_STATUS status; + uint32_t entries_read = 0; + uint32_t total_entries = 0; + uint32_t resume_handle = 0; + int found_group = 0; + const char *current_name = NULL; + uint8_t *buffer = NULL; + int i; + + struct GROUP_INFO_0 *info0 = NULL; + struct GROUP_INFO_1 *info1 = NULL; + struct GROUP_INFO_2 *info2 = NULL; + struct GROUP_INFO_3 *info3 = NULL; + + torture_comment(tctx, "testing NetGroupEnum level %d\n", level); + + do { + status = NetGroupEnum(hostname, + level, + &buffer, + (uint32_t)-1, + &entries_read, + &total_entries, + &resume_handle); + if (status == 0 || status == ERROR_MORE_DATA) { + switch (level) { + case 0: + info0 = (struct GROUP_INFO_0 *)buffer; + break; + case 1: + info1 = (struct GROUP_INFO_1 *)buffer; + break; + case 2: + info2 = (struct GROUP_INFO_2 *)buffer; + break; + case 3: + info3 = (struct GROUP_INFO_3 *)buffer; + break; + default: + return -1; + } + + for (i=0; i<entries_read; i++) { + + switch (level) { + case 0: + current_name = info0->grpi0_name; + break; + case 1: + current_name = info1->grpi1_name; + break; + case 2: + current_name = info2->grpi2_name; + break; + case 3: + current_name = info3->grpi3_name; + break; + default: + break; + } + + if (strcasecmp(current_name, groupname) == 0) { + found_group = 1; + } + + switch (level) { + case 0: + info0++; + break; + case 1: + info1++; + break; + case 2: + info2++; + break; + case 3: + info3++; + break; + } + } + NetApiBufferFree(buffer); + } + } while (status == ERROR_MORE_DATA); + + if (status) { + return status; + } + + if (!found_group) { + torture_comment(tctx, "failed to get group\n"); + return -1; + } + + return 0; +} + +static NET_API_STATUS test_netgroupgetusers(struct torture_context *tctx, + const char *hostname, + uint32_t level, + const char *groupname, + const char *username) +{ + NET_API_STATUS status; + uint32_t entries_read = 0; + uint32_t total_entries = 0; + uint32_t resume_handle = 0; + int found_user = 0; + const char *current_name = NULL; + uint8_t *buffer = NULL; + int i; + + struct GROUP_USERS_INFO_0 *info0 = NULL; + struct GROUP_USERS_INFO_1 *info1 = NULL; + + torture_comment(tctx, "testing NetGroupGetUsers level %d\n", level); + + do { + status = NetGroupGetUsers(hostname, + groupname, + level, + &buffer, + (uint32_t)-1, + &entries_read, + &total_entries, + &resume_handle); + if (status == 0 || status == ERROR_MORE_DATA) { + + switch (level) { + case 0: + info0 = (struct GROUP_USERS_INFO_0 *)buffer; + break; + case 1: + info1 = (struct GROUP_USERS_INFO_1 *)buffer; + break; + default: + break; + } + for (i=0; i<entries_read; i++) { + switch (level) { + case 0: + current_name = info0->grui0_name; + break; + case 1: + current_name = info1->grui1_name; + break; + default: + break; + } + + if (username && strcasecmp(current_name, username) == 0) { + found_user = 1; + } + + switch (level) { + case 0: + info0++; + break; + case 1: + info1++; + break; + } + } + NetApiBufferFree(buffer); + } + } while (status == ERROR_MORE_DATA); + + if (status) { + return status; + } + + if (username && !found_user) { + torture_comment(tctx, "failed to get user\n"); + return -1; + } + + return 0; +} + +static NET_API_STATUS test_netgroupsetusers(struct torture_context *tctx, + const char *hostname, + const char *groupname, + uint32_t level, + size_t num_entries, + const char **names) +{ + NET_API_STATUS status; + uint8_t *buffer = NULL; + int i = 0; + size_t buf_size = 0; + + struct GROUP_USERS_INFO_0 *g0 = NULL; + struct GROUP_USERS_INFO_1 *g1 = NULL; + + torture_comment(tctx, "testing NetGroupSetUsers level %d\n", level); + + switch (level) { + case 0: + buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries; + + status = NetApiBufferAllocate(buf_size, (void **)&g0); + if (status) { + goto out; + } + + for (i=0; i<num_entries; i++) { + g0[i].grui0_name = names[i]; + } + + buffer = (uint8_t *)g0; + break; + case 1: + buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries; + + status = NetApiBufferAllocate(buf_size, (void **)&g1); + if (status) { + goto out; + } + + for (i=0; i<num_entries; i++) { + g1[i].grui1_name = names[i]; + } + + buffer = (uint8_t *)g1; + break; + default: + break; + } + + /* NetGroupSetUsers */ + + status = NetGroupSetUsers(hostname, + groupname, + level, + buffer, + num_entries); + if (status) { + goto out; + } + + out: + NetApiBufferFree(buffer); + return status; +} + +bool torture_libnetapi_group(struct torture_context *tctx) +{ + NET_API_STATUS status = 0; + const char *username, *groupname, *groupname2; + uint8_t *buffer = NULL; + struct GROUP_INFO_0 g0; + uint32_t parm_err = 0; + uint32_t levels[] = { 0, 1, 2, 3}; + uint32_t enum_levels[] = { 0, 1, 2, 3}; + uint32_t getmem_levels[] = { 0, 1}; + int i; + const char *hostname = torture_setting_string(tctx, "host", NULL); + struct libnetapi_ctx *ctx; + + torture_assert(tctx, torture_libnetapi_init_context(tctx, &ctx), + "failed to initialize libnetapi"); + + torture_comment(tctx, "NetGroup tests\n"); + + username = "torture_test_user"; + groupname = "torture_test_group"; + groupname2 = "torture_test_group2"; + + /* cleanup */ + NetGroupDel(hostname, groupname); + NetGroupDel(hostname, groupname2); + NetUserDel(hostname, username); + + /* add a group */ + + g0.grpi0_name = groupname; + + torture_comment(tctx, "testing NetGroupAdd\n"); + + status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupAdd"); + goto out; + } + + /* 2nd add must fail */ + + status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err); + if (status == 0) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupAdd"); + status = -1; + goto out; + } + + /* test enum */ + + for (i=0; i<ARRAY_SIZE(enum_levels); i++) { + + status = test_netgroupenum(tctx, hostname, enum_levels[i], groupname); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupEnum"); + goto out; + } + } + + /* basic queries */ + + for (i=0; i<ARRAY_SIZE(levels); i++) { + + torture_comment(tctx, "testing NetGroupGetInfo level %d\n", levels[i]); + + status = NetGroupGetInfo(hostname, groupname, levels[i], &buffer); + if (status && status != 124) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetInfo"); + goto out; + } + } + + /* group rename */ + + g0.grpi0_name = groupname2; + + torture_comment(tctx, "testing NetGroupSetInfo level 0\n"); + + status = NetGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err); + switch (status) { + case 0: + break; + case 50: /* not supported */ + case 124: /* not implemented */ + groupname2 = groupname; + goto skip_rename; + default: + NETAPI_STATUS(tctx, ctx, status, "NetGroupSetInfo"); + goto out; + } + + /* should not exist anymore */ + + status = NetGroupDel(hostname, groupname); + if (status == 0) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupDel"); + goto out; + } + + skip_rename: + /* query info */ + + for (i=0; i<ARRAY_SIZE(levels); i++) { + + status = NetGroupGetInfo(hostname, groupname2, levels[i], &buffer); + if (status && status != 124) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetInfo"); + goto out; + } + } + + /* add user to group */ + + status = test_netuseradd(tctx, hostname, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserAdd"); + goto out; + } + + /* should not be member */ + + for (i=0; i<ARRAY_SIZE(getmem_levels); i++) { + + status = test_netgroupgetusers(tctx, hostname, getmem_levels[i], groupname2, NULL); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers"); + goto out; + } + } + + torture_comment(tctx, "testing NetGroupAddUser\n"); + + status = NetGroupAddUser(hostname, groupname2, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupAddUser"); + goto out; + } + + /* should be member */ + + for (i=0; i<ARRAY_SIZE(getmem_levels); i++) { + + status = test_netgroupgetusers(tctx, hostname, getmem_levels[i], groupname2, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers"); + goto out; + } + } + + torture_comment(tctx, "testing NetGroupDelUser\n"); + + status = NetGroupDelUser(hostname, groupname2, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupDelUser"); + goto out; + } + + /* should not be member */ + + status = test_netgroupgetusers(tctx, hostname, 0, groupname2, NULL); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers"); + goto out; + } + + /* set it again via exlicit member set */ + + status = test_netgroupsetusers(tctx, hostname, groupname2, 0, 1, &username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupSetUsers"); + goto out; + } + + /* should be member */ + + status = test_netgroupgetusers(tctx, hostname, 0, groupname2, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers"); + goto out; + } +#if 0 + /* wipe out member list */ + + status = test_netgroupsetusers(hostname, groupname2, 0, 0, NULL); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupSetUsers"); + goto out; + } + + /* should not be member */ + + status = test_netgroupgetusers(hostname, 0, groupname2, NULL); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers"); + goto out; + } +#endif + status = NetUserDel(hostname, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserDel"); + goto out; + } + + /* delete */ + + torture_comment(tctx, "testing NetGroupDel\n"); + + status = NetGroupDel(hostname, groupname2); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetGroupDel"); + goto out; + }; + + /* should not exist anymore */ + + status = NetGroupGetInfo(hostname, groupname2, 0, &buffer); + if (status == 0) { + NETAPI_STATUS_MSG(tctx, ctx, status, "NetGroupGetInfo", "expected failure and error code"); + status = -1; + goto out; + }; + + status = 0; + + torture_comment(tctx, "NetGroup tests succeeded\n"); + out: + if (status != 0) { + torture_comment(tctx, "NetGroup testsuite failed with: %s\n", + libnetapi_get_error_string(ctx, status)); + libnetapi_free(ctx); + return false; + } + + libnetapi_free(ctx); + return true; +} diff --git a/source4/torture/libnetapi/libnetapi_user.c b/source4/torture/libnetapi/libnetapi_user.c new file mode 100644 index 0000000000..c6343301e3 --- /dev/null +++ b/source4/torture/libnetapi/libnetapi_user.c @@ -0,0 +1,476 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/smbtorture.h" +#include <netapi.h> +#include "torture/libnetapi/proto.h" + +#define TORTURE_TEST_USER "testuser" + +#define NETAPI_STATUS(tctx, x,y,fn) \ + torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d)\n", \ + __LINE__, fn, libnetapi_get_error_string(x,y), y); + +static NET_API_STATUS test_netuserenum(struct torture_context *tctx, + const char *hostname, + uint32_t level, + const char *username) +{ + NET_API_STATUS status; + uint32_t entries_read = 0; + uint32_t total_entries = 0; + uint32_t resume_handle = 0; + const char *current_name = NULL; + int found_user = 0; + uint8_t *buffer = NULL; + int i; + + struct USER_INFO_0 *info0 = NULL; + struct USER_INFO_1 *info1 = NULL; + struct USER_INFO_2 *info2 = NULL; + struct USER_INFO_3 *info3 = NULL; + struct USER_INFO_4 *info4 = NULL; + struct USER_INFO_10 *info10 = NULL; + struct USER_INFO_11 *info11 = NULL; + struct USER_INFO_20 *info20 = NULL; + struct USER_INFO_23 *info23 = NULL; + + torture_comment(tctx, "testing NetUserEnum level %d\n", level); + + do { + status = NetUserEnum(hostname, + level, + FILTER_NORMAL_ACCOUNT, + &buffer, + (uint32_t)-1, + &entries_read, + &total_entries, + &resume_handle); + if (status == 0 || status == ERROR_MORE_DATA) { + switch (level) { + case 0: + info0 = (struct USER_INFO_0 *)buffer; + break; + case 1: + info1 = (struct USER_INFO_1 *)buffer; + break; + case 2: + info2 = (struct USER_INFO_2 *)buffer; + break; + case 3: + info3 = (struct USER_INFO_3 *)buffer; + break; + case 4: + info4 = (struct USER_INFO_4 *)buffer; + break; + case 10: + info10 = (struct USER_INFO_10 *)buffer; + break; + case 11: + info11 = (struct USER_INFO_11 *)buffer; + break; + case 20: + info20 = (struct USER_INFO_20 *)buffer; + break; + case 23: + info23 = (struct USER_INFO_23 *)buffer; + break; + default: + return -1; + } + + for (i=0; i<entries_read; i++) { + + switch (level) { + case 0: + current_name = info0->usri0_name; + break; + case 1: + current_name = info1->usri1_name; + break; + case 2: + current_name = info2->usri2_name; + break; + case 3: + current_name = info3->usri3_name; + break; + case 4: + current_name = info4->usri4_name; + break; + case 10: + current_name = info10->usri10_name; + break; + case 11: + current_name = info11->usri11_name; + break; + case 20: + current_name = info20->usri20_name; + break; + case 23: + current_name = info23->usri23_name; + break; + default: + return -1; + } + + if (strcasecmp(current_name, username) == 0) { + found_user = 1; + } + + switch (level) { + case 0: + info0++; + break; + case 1: + info1++; + break; + case 2: + info2++; + break; + case 3: + info3++; + break; + case 4: + info4++; + break; + case 10: + info10++; + break; + case 11: + info11++; + break; + case 20: + info20++; + break; + case 23: + info23++; + break; + default: + break; + } + } + NetApiBufferFree(buffer); + } + } while (status == ERROR_MORE_DATA); + + if (status) { + return status; + } + + if (!found_user) { + torture_comment(tctx, "failed to get user\n"); + return -1; + } + + return 0; +} + +NET_API_STATUS test_netuseradd(struct torture_context *tctx, + const char *hostname, + const char *username) +{ + struct USER_INFO_1 u1; + uint32_t parm_err = 0; + + ZERO_STRUCT(u1); + + torture_comment(tctx, "testing NetUserAdd\n"); + + u1.usri1_name = username; + u1.usri1_password = "W297!832jD8J"; + u1.usri1_password_age = 0; + u1.usri1_priv = 0; + u1.usri1_home_dir = NULL; + u1.usri1_comment = "User created using Samba NetApi Example code"; + u1.usri1_flags = 0; + u1.usri1_script_path = NULL; + + return NetUserAdd(hostname, 1, (uint8_t *)&u1, &parm_err); +} + +static NET_API_STATUS test_netusermodals(struct torture_context *tctx, + struct libnetapi_ctx *ctx, + const char *hostname) +{ + NET_API_STATUS status; + struct USER_MODALS_INFO_0 *u0 = NULL; + struct USER_MODALS_INFO_0 *_u0 = NULL; + uint8_t *buffer = NULL; + uint32_t parm_err = 0; + uint32_t levels[] = { 0, 1, 2, 3 }; + int i = 0; + + for (i=0; i<ARRAY_SIZE(levels); i++) { + + torture_comment(tctx, "testing NetUserModalsGet level %d\n", levels[i]); + + status = NetUserModalsGet(hostname, levels[i], &buffer); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet"); + return status; + } + } + + status = NetUserModalsGet(hostname, 0, (uint8_t **)&u0); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet"); + return status; + } + + torture_comment(tctx, "testing NetUserModalsSet\n"); + + status = NetUserModalsSet(hostname, 0, (uint8_t *)u0, &parm_err); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserModalsSet"); + return status; + } + + status = NetUserModalsGet(hostname, 0, (uint8_t **)&_u0); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet"); + return status; + } + + if (memcmp(u0, _u0, sizeof(u0) != 0)) { + torture_comment(tctx, "USER_MODALS_INFO_0 struct has changed!!!!\n"); + return -1; + } + + return 0; +} + +static NET_API_STATUS test_netusergetgroups(struct torture_context *tctx, + const char *hostname, + uint32_t level, + const char *username, + const char *groupname) +{ + NET_API_STATUS status; + uint32_t entries_read = 0; + uint32_t total_entries = 0; + const char *current_name; + int found_group = 0; + uint8_t *buffer = NULL; + int i; + + struct GROUP_USERS_INFO_0 *i0; + struct GROUP_USERS_INFO_1 *i1; + + torture_comment(tctx, "testing NetUserGetGroups level %d\n", level); + + do { + status = NetUserGetGroups(hostname, + username, + level, + &buffer, + (uint32_t)-1, + &entries_read, + &total_entries); + if (status == 0 || status == ERROR_MORE_DATA) { + switch (level) { + case 0: + i0 = (struct GROUP_USERS_INFO_0 *)buffer; + break; + case 1: + i1 = (struct GROUP_USERS_INFO_1 *)buffer; + break; + default: + return -1; + } + + for (i=0; i<entries_read; i++) { + + switch (level) { + case 0: + current_name = i0->grui0_name; + break; + case 1: + current_name = i1->grui1_name; + break; + default: + return -1; + } + + if (groupname && strcasecmp(current_name, groupname) == 0) { + found_group = 1; + } + + switch (level) { + case 0: + i0++; + break; + case 1: + i1++; + break; + default: + break; + } + } + NetApiBufferFree(buffer); + } + } while (status == ERROR_MORE_DATA); + + if (status) { + return status; + } + + if (groupname && !found_group) { + torture_comment(tctx, "failed to get membership\n"); + return -1; + } + + return 0; +} + +bool torture_libnetapi_user(struct torture_context *tctx) +{ + NET_API_STATUS status = 0; + const char *username, *username2; + uint8_t *buffer = NULL; + uint32_t levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 }; + uint32_t enum_levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 }; + uint32_t getgr_levels[] = { 0, 1 }; + int i; + + struct USER_INFO_1007 u1007; + uint32_t parm_err = 0; + + const char *hostname = torture_setting_string(tctx, "host", NULL); + struct libnetapi_ctx *ctx; + + torture_assert(tctx, torture_libnetapi_init_context(tctx, &ctx), + "failed to initialize libnetapi"); + + torture_comment(tctx, "NetUser tests\n"); + + username = "torture_test_user"; + username2 = "torture_test_user2"; + + /* cleanup */ + NetUserDel(hostname, username); + NetUserDel(hostname, username2); + + /* add a user */ + + status = test_netuseradd(tctx, hostname, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserAdd"); + goto out; + } + + /* enum the new user */ + + for (i=0; i<ARRAY_SIZE(enum_levels); i++) { + + status = test_netuserenum(tctx, hostname, enum_levels[i], username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserEnum"); + goto out; + } + } + + /* basic queries */ + + for (i=0; i<ARRAY_SIZE(levels); i++) { + + torture_comment(tctx, "testing NetUserGetInfo level %d\n", levels[i]); + + status = NetUserGetInfo(hostname, username, levels[i], &buffer); + if (status && status != 124) { + NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo"); + goto out; + } + } + + /* testing getgroups */ + + for (i=0; i<ARRAY_SIZE(getgr_levels); i++) { + + status = test_netusergetgroups(tctx, hostname, getgr_levels[i], username, NULL); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserGetGroups"); + goto out; + } + } + + /* modify description */ + + torture_comment(tctx, "testing NetUserSetInfo level %d\n", 1007); + + u1007.usri1007_comment = "NetApi modified user"; + + status = NetUserSetInfo(hostname, username, 1007, (uint8_t *)&u1007, &parm_err); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserSetInfo"); + goto out; + } + + /* query info */ + + for (i=0; i<ARRAY_SIZE(levels); i++) { + status = NetUserGetInfo(hostname, username, levels[i], &buffer); + if (status && status != 124) { + NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo"); + goto out; + } + } + + /* delete */ + + torture_comment(tctx, "testing NetUserDel\n"); + + status = NetUserDel(hostname, username); + if (status) { + NETAPI_STATUS(tctx, ctx, status, "NetUserDel"); + goto out; + } + + /* should not exist anymore */ + + status = NetUserGetInfo(hostname, username, 0, &buffer); + if (status == 0) { + NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo"); + status = -1; + goto out; + } + + status = test_netusermodals(tctx, ctx, hostname); + if (status) { + goto out; + } + + status = 0; + + torture_comment(tctx, "NetUser tests succeeded\n"); + out: + /* cleanup */ + NetUserDel(hostname, username); + NetUserDel(hostname, username2); + + if (status != 0) { + torture_comment(tctx, "NetUser testsuite failed with: %s\n", + libnetapi_get_error_string(ctx, status)); + libnetapi_free(ctx); + return false; + } + + libnetapi_free(ctx); + return true; +} diff --git a/source4/torture/local/config.mk b/source4/torture/local/config.mk index 5c8c1d5762..28599e4bda 100644 --- a/source4/torture/local/config.mk +++ b/source4/torture/local/config.mk @@ -17,7 +17,8 @@ PRIVATE_DEPENDENCIES = \ TORTURE_LIBCRYPTO \ share \ torture_registry \ - PROVISION + PROVISION \ + NSS_WRAPPER # End SUBSYSTEM TORTURE_LOCAL ################################# @@ -34,6 +35,7 @@ TORTURE_LOCAL_OBJ_FILES = \ $(torturesrcdir)/../../lib/util/tests/idtree.o \ $(torturesrcdir)/../lib/socket/testsuite.o \ $(torturesrcdir)/../../lib/socket_wrapper/testsuite.o \ + $(torturesrcdir)/../../lib/nss_wrapper/testsuite.o \ $(torturesrcdir)/../libcli/resolve/testsuite.o \ $(torturesrcdir)/../../lib/util/tests/strlist.o \ $(torturesrcdir)/../../lib/util/tests/str.o \ diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c index a1b100edb8..73ee366dcd 100644 --- a/source4/torture/local/local.c +++ b/source4/torture/local/local.c @@ -43,6 +43,7 @@ torture_local_iconv, torture_local_socket, torture_local_socket_wrapper, + torture_local_nss_wrapper, torture_pac, torture_local_resolve, torture_local_sddl, diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 92ce66fef2..30e7e0889c 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -2673,21 +2673,20 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p, return true; } -static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx, - struct cli_credentials *machine_credentials, - struct cli_credentials *test_credentials, - struct netlogon_creds_CredentialState *creds, - NTSTATUS expected_result) +static bool test_SamLogon(struct torture_context *tctx, + struct dcerpc_pipe *p, + struct cli_credentials *test_credentials, + NTSTATUS expected_result) { NTSTATUS status; - struct netr_LogonSamLogon r; - struct netr_Authenticator auth, auth2; + struct netr_LogonSamLogonEx r; union netr_LogonLevel logon; union netr_Validation validation; uint8_t authoritative; struct netr_NetworkInfo ninfo; DATA_BLOB names_blob, chal, lm_resp, nt_resp; int flags = CLI_CRED_NTLM_AUTH; + uint32_t samlogon_flags = 0; if (lp_client_lanman_auth(tctx->lp_ctx)) { flags |= CLI_CRED_LANMAN_AUTH; @@ -2706,8 +2705,8 @@ static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *t chal = data_blob_const(ninfo.challenge, sizeof(ninfo.challenge)); - names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials), - cli_credentials_get_domain(machine_credentials)); + names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials), + cli_credentials_get_domain(test_credentials)); status = cli_credentials_get_ntlm_response(test_credentials, tctx, &flags, @@ -2728,56 +2727,38 @@ static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *t MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT; ninfo.identity_info.logon_id_low = 0; ninfo.identity_info.logon_id_high = 0; - ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials); + ninfo.identity_info.workstation.string = cli_credentials_get_workstation(test_credentials); logon.network = &ninfo; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); - r.in.computer_name = cli_credentials_get_workstation(machine_credentials); - r.in.credential = &auth; - r.in.return_authenticator = &auth2; - r.in.logon_level = 2; + r.in.computer_name = cli_credentials_get_workstation(test_credentials); + r.in.logon_level = NetlogonNetworkInformation; r.in.logon = &logon; + r.in.flags = &samlogon_flags; + r.out.flags = &samlogon_flags; r.out.validation = &validation; r.out.authoritative = &authoritative; d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string); - ZERO_STRUCT(auth2); - netlogon_creds_client_authenticator(creds, &auth); - - r.in.validation_level = 2; + r.in.validation_level = 6; - status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r); + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { + r.in.validation_level = 3; + status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r); + } if (!NT_STATUS_IS_OK(status)) { - torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed"); + torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed"); return true; } else { - torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); + torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed"); } - torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), - "Credential chaining failed"); - return true; } -static bool test_SamLogon(struct torture_context *tctx, - struct dcerpc_pipe *p, - struct cli_credentials *machine_credentials, - struct cli_credentials *test_credentials, - NTSTATUS expected_result) -{ - struct netlogon_creds_CredentialState *creds; - - if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) { - return false; - } - - return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials, - creds, expected_result); -} - static bool test_SamLogon_with_creds(struct torture_context *tctx, struct dcerpc_pipe *p, struct cli_credentials *machine_creds, @@ -2791,19 +2772,18 @@ static bool test_SamLogon_with_creds(struct torture_context *tctx, test_credentials = cli_credentials_init(tctx); cli_credentials_set_workstation(test_credentials, - TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED); + cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED); cli_credentials_set_domain(test_credentials, - lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED); + cli_credentials_get_domain(machine_creds), CRED_SPECIFIED); cli_credentials_set_username(test_credentials, acct_name, CRED_SPECIFIED); cli_credentials_set_password(test_credentials, password, CRED_SPECIFIED); - cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC); - printf("testing samlogon as %s@%s password: %s\n", - acct_name, TEST_ACCOUNT_NAME_PWD, password); + printf("testing samlogon as %s password: %s\n", + acct_name, password); - if (!test_SamLogon(tctx, p, machine_creds, test_credentials, + if (!test_SamLogon(tctx, p, test_credentials, expected_samlogon_result)) { torture_warning(tctx, "new password did not work\n"); ret = false; @@ -2886,11 +2866,12 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, struct cli_credentials *machine_credentials) { int s = 0, q = 0, f = 0, l = 0, z = 0; + struct dcerpc_binding *b; bool ret = true; - int delay = 500000; + int delay = 50000; bool set_levels[] = { false, true }; bool query_levels[] = { false, true }; - uint32_t levels[] = { 18, 21, 23, 24, 25, 26 }; + uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */ uint32_t nonzeros[] = { 1, 24 }; uint32_t fields_present[] = { 0, @@ -2915,19 +2896,41 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, delay); } - status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon); + status = torture_rpc_binding(tctx, &b); if (!NT_STATUS_IS_OK(status)) { - return false; + ret = false; + return ret; + } + + /* We have to use schannel, otherwise the SamLogonEx fails + * with INTERNAL_ERROR */ + + b->flags &= ~DCERPC_AUTH_OPTIONS; + b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128; + + status = dcerpc_pipe_connect_b(tctx, &np, b, + &ndr_table_netlogon, + machine_credentials, tctx->ev, tctx->lp_ctx); + + if (!NT_STATUS_IS_OK(status)) { + d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status)); + ret = false; + return ret; } /* set to 1 to enable testing for all possible opcode (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2) combinations */ #if 0 +#define TEST_ALL_LEVELS 1 #define TEST_SET_LEVELS 1 #define TEST_QUERY_LEVELS 1 #endif +#ifdef TEST_ALL_LEVELS for (l=0; l<ARRAY_SIZE(levels); l++) { +#else + for (l=0; l<(ARRAY_SIZE(levels))/2; l++) { +#endif for (z=0; z<ARRAY_SIZE(nonzeros); z++) { for (f=0; f<ARRAY_SIZE(fields_present); f++) { #ifdef TEST_SET_LEVELS @@ -4373,7 +4376,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK }, { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER }, { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER }, - { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK }, + { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED }, { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER }, { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER }, { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER }, @@ -6177,6 +6180,8 @@ static bool test_ManyObjects(struct dcerpc_pipe *p, NTSTATUS status; uint32_t i; + struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total); + /* query */ { @@ -6209,29 +6214,25 @@ static bool test_ManyObjects(struct dcerpc_pipe *p, for (i=0; i < num_total; i++) { - struct policy_handle handle; const char *name = NULL; - ZERO_STRUCT(handle); - switch (which_ops) { case TORTURE_SAMR_MANY_ACCOUNTS: name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i); - ret &= test_CreateUser(p, tctx, domain_handle, name, &handle, domain_sid, 0, NULL, false); + ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false); break; case TORTURE_SAMR_MANY_GROUPS: name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i); - ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handle, domain_sid, false); + ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false); break; case TORTURE_SAMR_MANY_ALIASES: name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i); - ret &= test_CreateAlias(p, tctx, domain_handle, name, &handle, domain_sid, false); + ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false); break; default: return false; } - if (!policy_handle_empty(&handle)) { - ret &= test_samr_handle_Close(p, tctx, &handle); + if (!policy_handle_empty(&handles[i])) { num_created++; } } @@ -6252,9 +6253,6 @@ static bool test_ManyObjects(struct dcerpc_pipe *p, return false; } - torture_assert_int_equal(tctx, num_enum, num_anounced + num_created, - "unexpected number of results returned in enum call"); -#if 0 /* TODO: dispinfo */ switch (which_ops) { @@ -6268,9 +6266,38 @@ static bool test_ManyObjects(struct dcerpc_pipe *p, return false; } + + /* delete */ + + for (i=0; i < num_total; i++) { + + if (policy_handle_empty(&handles[i])) { + continue; + } + + switch (which_ops) { + case TORTURE_SAMR_MANY_ACCOUNTS: + ret &= test_DeleteUser(p, tctx, &handles[i]); + break; + case TORTURE_SAMR_MANY_GROUPS: + ret &= test_DeleteDomainGroup(p, tctx, &handles[i]); + break; + case TORTURE_SAMR_MANY_ALIASES: + ret &= test_DeleteAlias(p, tctx, &handles[i]); + break; + default: + return false; + } + } + + talloc_free(handles); + +#if 0 torture_assert_int_equal(tctx, num_disp, num_anounced + num_created, "unexpected number of results returned in dispinfo call"); #endif + torture_assert_int_equal(tctx, num_enum, num_anounced + num_created, + "unexpected number of results returned in enum call"); return ret; } @@ -6310,9 +6337,14 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, ret &= test_samr_handle_Close(p, tctx, handle); switch (which_ops) { - case TORTURE_SAMR_USER_ATTRIBUTES: - case TORTURE_SAMR_USER_PRIVILEGES: case TORTURE_SAMR_PASSWORDS: + case TORTURE_SAMR_USER_PRIVILEGES: + if (!torture_setting_bool(tctx, "samba3", false)) { + ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL); + } + ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true); + break; + case TORTURE_SAMR_USER_ATTRIBUTES: if (!torture_setting_bool(tctx, "samba3", false)) { ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL); } diff --git a/source4/torture/torture.c b/source4/torture/torture.c index a9ec325dd6..d80acffa0d 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -45,6 +45,12 @@ bool torture_register_suite(struct torture_suite *suite) return torture_suite_add_suite(torture_root, suite); } +#ifndef HAVE_NETAPI_H +NTSTATUS torture_libnetapi_init(void) +{ + return NT_STATUS_OK; +} +#endif _PUBLIC_ int torture_init(void) { @@ -57,6 +63,9 @@ _PUBLIC_ int torture_init(void) extern NTSTATUS torture_rpc_init(void); extern NTSTATUS torture_smb2_init(void); extern NTSTATUS torture_net_init(void); +#ifdef HAVE_NETAPI_H + extern NTSTATUS torture_libnetapi_init(void); +#endif extern NTSTATUS torture_raw_init(void); extern NTSTATUS torture_unix_init(void); extern NTSTATUS torture_winbind_init(void); |