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 /source3 | |
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
Diffstat (limited to 'source3')
45 files changed, 1975 insertions, 2286 deletions
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/include/wbc_async.h b/source3/include/wbc_async.h deleted file mode 100644 index 57625d5baf..0000000000 --- a/source3/include/wbc_async.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Headers for the async winbind client library - Copyright (C) Kai Blin 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/>. -*/ - -#ifndef _WBC_ASYNC_H_ -#define _WBC_ASYNC_H_ - -#include "nsswitch/libwbclient/wbclient.h" - -struct wb_context; - -struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct wb_context *wb_ctx, bool need_priv, - 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); - -/* Definitions from wb_reqtrans.c */ -wbcErr map_wbc_err_from_errno(int error); - -bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err); -wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req); - -struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd, size_t max_extra_data); -ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_request **preq, int *err); - -struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_request *wb_req); -ssize_t wb_req_write_recv(struct tevent_req *req, int *err); - -struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, int fd); -ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp, int *err); - -struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_response *wb_resp); -ssize_t wb_resp_write_recv(struct tevent_req *req, int *err); - -struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_request *wb_req); -int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presponse, int *err); - -#endif /*_WBC_ASYNC_H_*/ 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/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c deleted file mode 100644 index 55883ba8c7..0000000000 --- a/source3/lib/wb_reqtrans.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Async transfer of winbindd_request and _response structs - - 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. - - 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 "wbc_async.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -struct req_read_state { - struct winbindd_request *wb_req; - size_t max_extra_data; - ssize_t ret; -}; - -static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data); -static void wb_req_read_done(struct tevent_req *subreq); - -struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd, size_t max_extra_data) -{ - struct tevent_req *req, *subreq; - struct req_read_state *state; - - req = tevent_req_create(mem_ctx, &state, struct req_read_state); - if (req == NULL) { - return NULL; - } - state->max_extra_data = max_extra_data; - - subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, wb_req_read_done, req); - return req; -} - -static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data) -{ - struct req_read_state *state = talloc_get_type_abort( - private_data, struct req_read_state); - struct winbindd_request *req = (struct winbindd_request *)buf; - - if (buflen == 4) { - if (req->length != sizeof(struct winbindd_request)) { - DEBUG(0, ("wb_req_read_len: Invalid request size " - "received: %d (expected %d)\n", - (int)req->length, - (int)sizeof(struct winbindd_request))); - return -1; - } - return sizeof(struct winbindd_request) - 4; - } - - if ((state->max_extra_data != 0) - && (req->extra_len > state->max_extra_data)) { - DEBUG(3, ("Got request with %d bytes extra data on " - "unprivileged socket\n", (int)req->extra_len)); - return -1; - } - - return req->extra_len; -} - -static void wb_req_read_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct req_read_state *state = tevent_req_data( - req, struct req_read_state); - int err; - uint8_t *buf; - - state->ret = read_packet_recv(subreq, state, &buf, &err); - TALLOC_FREE(subreq); - if (state->ret == -1) { - tevent_req_error(req, err); - return; - } - - state->wb_req = (struct winbindd_request *)buf; - - if (state->wb_req->extra_len != 0) { - state->wb_req->extra_data.data = - (char *)buf + sizeof(struct winbindd_request); - } else { - state->wb_req->extra_data.data = NULL; - } - tevent_req_done(req); -} - -ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_request **preq, int *err) -{ - struct req_read_state *state = tevent_req_data( - req, struct req_read_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - *preq = talloc_move(mem_ctx, &state->wb_req); - return state->ret; -} - -struct req_write_state { - struct iovec iov[2]; - ssize_t ret; -}; - -static void wb_req_write_done(struct tevent_req *subreq); - -struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_request *wb_req) -{ - struct tevent_req *req, *subreq; - struct req_write_state *state; - int count = 1; - - req = tevent_req_create(mem_ctx, &state, struct req_write_state); - if (req == NULL) { - return NULL; - } - - state->iov[0].iov_base = (void *)wb_req; - state->iov[0].iov_len = sizeof(struct winbindd_request); - - if (wb_req->extra_len != 0) { - state->iov[1].iov_base = (void *)wb_req->extra_data.data; - state->iov[1].iov_len = wb_req->extra_len; - count = 2; - } - - subreq = writev_send(state, ev, queue, fd, true, state->iov, count); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, wb_req_write_done, req); - return req; -} - -static void wb_req_write_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct req_write_state *state = tevent_req_data( - req, struct req_write_state); - int err; - - state->ret = writev_recv(subreq, &err); - TALLOC_FREE(subreq); - if (state->ret < 0) { - tevent_req_error(req, err); - return; - } - tevent_req_done(req); -} - -ssize_t wb_req_write_recv(struct tevent_req *req, int *err) -{ - struct req_write_state *state = tevent_req_data( - req, struct req_write_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - return state->ret; -} - -struct resp_read_state { - struct winbindd_response *wb_resp; - ssize_t ret; -}; - -static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data); -static void wb_resp_read_done(struct tevent_req *subreq); - -struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, int fd) -{ - struct tevent_req *req, *subreq; - struct resp_read_state *state; - - req = tevent_req_create(mem_ctx, &state, struct resp_read_state); - if (req == NULL) { - return NULL; - } - - subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, wb_resp_read_done, req); - return req; -} - -static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data) -{ - struct winbindd_response *resp = (struct winbindd_response *)buf; - - if (buflen == 4) { - if (resp->length < sizeof(struct winbindd_response)) { - DEBUG(0, ("wb_resp_read_len: Invalid response size " - "received: %d (expected at least%d)\n", - (int)resp->length, - (int)sizeof(struct winbindd_response))); - return -1; - } - } - return resp->length - buflen; -} - -static void wb_resp_read_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct resp_read_state *state = tevent_req_data( - req, struct resp_read_state); - uint8_t *buf; - int err; - - state->ret = read_packet_recv(subreq, state, &buf, &err); - TALLOC_FREE(subreq); - if (state->ret == -1) { - tevent_req_error(req, err); - return; - } - - state->wb_resp = (struct winbindd_response *)buf; - - if (state->wb_resp->length > sizeof(struct winbindd_response)) { - state->wb_resp->extra_data.data = - (char *)buf + sizeof(struct winbindd_response); - } else { - state->wb_resp->extra_data.data = NULL; - } - tevent_req_done(req); -} - -ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp, int *err) -{ - struct resp_read_state *state = tevent_req_data( - req, struct resp_read_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - *presp = talloc_move(mem_ctx, &state->wb_resp); - return state->ret; -} - -struct resp_write_state { - struct iovec iov[2]; - ssize_t ret; -}; - -static void wb_resp_write_done(struct tevent_req *subreq); - -struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_response *wb_resp) -{ - struct tevent_req *req, *subreq; - struct resp_write_state *state; - int count = 1; - - req = tevent_req_create(mem_ctx, &state, struct resp_write_state); - if (req == NULL) { - return NULL; - } - - state->iov[0].iov_base = (void *)wb_resp; - state->iov[0].iov_len = sizeof(struct winbindd_response); - - if (wb_resp->length > sizeof(struct winbindd_response)) { - state->iov[1].iov_base = (void *)wb_resp->extra_data.data; - state->iov[1].iov_len = - wb_resp->length - sizeof(struct winbindd_response); - count = 2; - } - - subreq = writev_send(state, ev, queue, fd, true, state->iov, count); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, wb_resp_write_done, req); - return req; -} - -static void wb_resp_write_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct resp_write_state *state = tevent_req_data( - req, struct resp_write_state); - int err; - - state->ret = writev_recv(subreq, &err); - TALLOC_FREE(subreq); - if (state->ret < 0) { - tevent_req_error(req, err); - return; - } - tevent_req_done(req); -} - -ssize_t wb_resp_write_recv(struct tevent_req *req, int *err) -{ - struct resp_write_state *state = tevent_req_data( - req, struct resp_write_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - return state->ret; -} - -struct wb_simple_trans_state { - struct tevent_context *ev; - int fd; - struct winbindd_response *wb_resp; -}; - -static void wb_simple_trans_write_done(struct tevent_req *subreq); -static void wb_simple_trans_read_done(struct tevent_req *subreq); - -struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tevent_queue *queue, int fd, - struct winbindd_request *wb_req) -{ - struct tevent_req *req, *subreq; - struct wb_simple_trans_state *state; - - req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state); - if (req == NULL) { - return NULL; - } - - wb_req->length = sizeof(struct winbindd_request); - - state->ev = ev; - state->fd = fd; - - subreq = wb_req_write_send(state, ev, queue, fd, wb_req); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, wb_simple_trans_write_done, req); - - return req; -} - -static void wb_simple_trans_write_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_simple_trans_state *state = tevent_req_data( - req, struct wb_simple_trans_state); - ssize_t ret; - int err; - - ret = wb_req_write_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret == -1) { - tevent_req_error(req, err); - return; - } - subreq = wb_resp_read_send(state, state->ev, state->fd); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_simple_trans_read_done, req); -} - -static void wb_simple_trans_read_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_simple_trans_state *state = tevent_req_data( - req, struct wb_simple_trans_state); - ssize_t ret; - int err; - - ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err); - TALLOC_FREE(subreq); - if (ret == -1) { - tevent_req_error(req, err); - return; - } - - tevent_req_done(req); -} - -int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presponse, int *err) -{ - struct wb_simple_trans_state *state = tevent_req_data( - req, struct wb_simple_trans_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - *presponse = talloc_move(mem_ctx, &state->wb_resp); - return 0; -} diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c deleted file mode 100644 index 164cfc9691..0000000000 --- a/source3/lib/wbclient.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - Unix SMB/CIFS implementation. - 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. - - 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 "wbc_async.h" - -wbcErr map_wbc_err_from_errno(int error) -{ - switch(error) { - case EPERM: - case EACCES: - return WBC_ERR_AUTH_ERROR; - case ENOMEM: - return WBC_ERR_NO_MEMORY; - case EIO: - default: - return WBC_ERR_UNKNOWN_FAILURE; - } -} - -bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err) -{ - enum tevent_req_state state; - uint64_t error; - if (!tevent_req_is_error(req, &state, &error)) { - *pwbc_err = WBC_ERR_SUCCESS; - return false; - } - - switch (state) { - case TEVENT_REQ_USER_ERROR: - *pwbc_err = error; - break; - case TEVENT_REQ_TIMED_OUT: - *pwbc_err = WBC_ERR_UNKNOWN_FAILURE; - break; - case TEVENT_REQ_NO_MEMORY: - *pwbc_err = WBC_ERR_NO_MEMORY; - break; - default: - *pwbc_err = WBC_ERR_UNKNOWN_FAILURE; - break; - } - return true; -} - -wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req) -{ - wbcErr wbc_err; - - if (tevent_req_is_wbcerr(req, &wbc_err)) { - return wbc_err; - } - - return WBC_ERR_SUCCESS; -} - -struct wb_context { - struct tevent_queue *queue; - int fd; - bool is_priv; -}; - -static int make_nonstd_fd(int fd) -{ - int i; - int sys_errno = 0; - int fds[3]; - int num_fds = 0; - - if (fd == -1) { - return -1; - } - while (fd < 3) { - fds[num_fds++] = fd; - fd = dup(fd); - if (fd == -1) { - sys_errno = errno; - break; - } - } - for (i=0; i<num_fds; i++) { - close(fds[i]); - } - if (fd == -1) { - errno = sys_errno; - } - return fd; -} - -/**************************************************************************** - Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, - else - if SYSV use O_NDELAY - if BSD use FNDELAY - Set close on exec also. -****************************************************************************/ - -static int make_safe_fd(int fd) -{ - int result, flags; - int new_fd = make_nonstd_fd(fd); - - if (new_fd == -1) { - goto fail; - } - - /* Socket should be nonblocking. */ - -#ifdef O_NONBLOCK -#define FLAG_TO_SET O_NONBLOCK -#else -#ifdef SYSV -#define FLAG_TO_SET O_NDELAY -#else /* BSD */ -#define FLAG_TO_SET FNDELAY -#endif -#endif - - if ((flags = fcntl(new_fd, F_GETFL)) == -1) { - goto fail; - } - - flags |= FLAG_TO_SET; - if (fcntl(new_fd, F_SETFL, flags) == -1) { - goto fail; - } - -#undef FLAG_TO_SET - - /* Socket should be closed on exec() */ -#ifdef FD_CLOEXEC - result = flags = fcntl(new_fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl( new_fd, F_SETFD, flags ); - } - if (result < 0) { - goto fail; - } -#endif - return new_fd; - - fail: - if (new_fd != -1) { - int sys_errno = errno; - close(new_fd); - errno = sys_errno; - } - return -1; -} - -struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) -{ - struct wb_context *result; - - result = talloc(mem_ctx, struct wb_context); - if (result == NULL) { - return NULL; - } - result->queue = tevent_queue_create(result, "wb_trans"); - if (result->queue == NULL) { - TALLOC_FREE(result); - return NULL; - } - result->fd = -1; - result->is_priv = false; - return result; -} - -struct wb_connect_state { - int dummy; -}; - -static void wbc_connect_connected(struct tevent_req *subreq); - -static struct tevent_req *wb_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct wb_context *wb_ctx, - const char *dir) -{ - struct tevent_req *result, *subreq; - struct wb_connect_state *state; - struct sockaddr_un sunaddr; - struct stat st; - char *path = NULL; - wbcErr wbc_err; - - result = tevent_req_create(mem_ctx, &state, struct wb_connect_state); - if (result == NULL) { - return NULL; - } - - if (wb_ctx->fd != -1) { - close(wb_ctx->fd); - wb_ctx->fd = -1; - } - - /* Check permissions on unix socket directory */ - - if (lstat(dir, &st) == -1) { - wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; - goto post_status; - } - - if (!S_ISDIR(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; - goto post_status; - } - - /* Connect to socket */ - - path = talloc_asprintf(talloc_tos(), "%s/%s", dir, - WINBINDD_SOCKET_NAME); - if (path == NULL) { - goto nomem; - } - - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)); - TALLOC_FREE(path); - - /* If socket file doesn't exist, don't bother trying to connect - with retry. This is an attempt to make the system usable when - the winbindd daemon is not running. */ - - if ((lstat(sunaddr.sun_path, &st) == -1) - || !S_ISSOCK(st.st_mode) - || (st.st_uid != 0 && st.st_uid != geteuid())) { - wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; - goto post_status; - } - - wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0)); - if (wb_ctx->fd == -1) { - wbc_err = map_wbc_err_from_errno(errno); - goto post_status; - } - - subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd, - (struct sockaddr *)(void *)&sunaddr, - sizeof(sunaddr)); - if (subreq == NULL) { - goto nomem; - } - tevent_req_set_callback(subreq, wbc_connect_connected, result); - return result; - - post_status: - tevent_req_error(result, wbc_err); - return tevent_req_post(result, ev); - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wbc_connect_connected(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - int res, err; - - res = async_connect_recv(subreq, &err); - TALLOC_FREE(subreq); - if (res == -1) { - tevent_req_error(req, map_wbc_err_from_errno(err)); - return; - } - tevent_req_done(req); -} - -static wbcErr wb_connect_recv(struct tevent_req *req) -{ - return tevent_req_simple_recv_wbcerr(req); -} - -static const char *winbindd_socket_dir(void) -{ -#ifdef SOCKET_WRAPPER - const char *env_dir; - - env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); - if (env_dir) { - return env_dir; - } -#endif - - return WINBINDD_SOCKET_DIR; -} - -struct wb_open_pipe_state { - struct wb_context *wb_ctx; - struct tevent_context *ev; - bool need_priv; - struct winbindd_request wb_req; -}; - -static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq); -static void wb_open_pipe_ping_done(struct tevent_req *subreq); -static void wb_open_pipe_getpriv_done(struct tevent_req *subreq); -static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq); - -static struct tevent_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct wb_context *wb_ctx, - bool need_priv) -{ - struct tevent_req *result, *subreq; - struct wb_open_pipe_state *state; - - result = tevent_req_create(mem_ctx, &state, struct wb_open_pipe_state); - if (result == NULL) { - return NULL; - } - state->wb_ctx = wb_ctx; - state->ev = ev; - state->need_priv = need_priv; - - if (wb_ctx->fd != -1) { - close(wb_ctx->fd); - wb_ctx->fd = -1; - } - - subreq = wb_connect_send(state, ev, wb_ctx, winbindd_socket_dir()); - if (subreq == NULL) { - goto fail; - } - tevent_req_set_callback(subreq, wb_open_pipe_connect_nonpriv_done, - result); - return result; - - fail: - TALLOC_FREE(result); - return NULL; -} - -static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_open_pipe_state *state = tevent_req_data( - req, struct wb_open_pipe_state); - wbcErr wbc_err; - - wbc_err = wb_connect_recv(subreq); - TALLOC_FREE(subreq); - if (!WBC_ERROR_IS_OK(wbc_err)) { - state->wb_ctx->is_priv = true; - tevent_req_error(req, wbc_err); - return; - } - - ZERO_STRUCT(state->wb_req); - state->wb_req.cmd = WINBINDD_INTERFACE_VERSION; - state->wb_req.pid = getpid(); - - subreq = wb_simple_trans_send(state, state->ev, NULL, - state->wb_ctx->fd, &state->wb_req); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_open_pipe_ping_done, req); -} - -static void wb_open_pipe_ping_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_open_pipe_state *state = tevent_req_data( - req, struct wb_open_pipe_state); - struct winbindd_response *wb_resp; - int ret, err; - - ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err); - TALLOC_FREE(subreq); - if (ret == -1) { - tevent_req_error(req, map_wbc_err_from_errno(err)); - return; - } - - if (!state->need_priv) { - tevent_req_done(req); - return; - } - - state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR; - state->wb_req.pid = getpid(); - - subreq = wb_simple_trans_send(state, state->ev, NULL, - state->wb_ctx->fd, &state->wb_req); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_open_pipe_getpriv_done, req); -} - -static void wb_open_pipe_getpriv_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_open_pipe_state *state = tevent_req_data( - req, struct wb_open_pipe_state); - struct winbindd_response *wb_resp = NULL; - int ret, err; - - ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err); - TALLOC_FREE(subreq); - if (ret == -1) { - tevent_req_error(req, map_wbc_err_from_errno(err)); - return; - } - - close(state->wb_ctx->fd); - state->wb_ctx->fd = -1; - - subreq = wb_connect_send(state, state->ev, state->wb_ctx, - (char *)wb_resp->extra_data.data); - TALLOC_FREE(wb_resp); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_open_pipe_connect_priv_done, req); -} - -static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_open_pipe_state *state = tevent_req_data( - req, struct wb_open_pipe_state); - wbcErr wbc_err; - - wbc_err = wb_connect_recv(subreq); - TALLOC_FREE(subreq); - if (!WBC_ERROR_IS_OK(wbc_err)) { - tevent_req_error(req, wbc_err); - return; - } - state->wb_ctx->is_priv = true; - tevent_req_done(req); -} - -static wbcErr wb_open_pipe_recv(struct tevent_req *req) -{ - return tevent_req_simple_recv_wbcerr(req); -} - -struct wb_trans_state { - struct wb_trans_state *prev, *next; - struct wb_context *wb_ctx; - struct tevent_context *ev; - struct winbindd_request *wb_req; - struct winbindd_response *wb_resp; - bool need_priv; -}; - -static bool closed_fd(int fd) -{ - struct timeval tv; - fd_set r_fds; - int selret; - - if (fd == -1) { - return true; - } - - FD_ZERO(&r_fds); - FD_SET(fd, &r_fds); - ZERO_STRUCT(tv); - - selret = select(fd+1, &r_fds, NULL, NULL, &tv); - if (selret == -1) { - return true; - } - if (selret == 0) { - return false; - } - return (FD_ISSET(fd, &r_fds)); -} - -static void wb_trans_trigger(struct tevent_req *req, void *private_data); -static void wb_trans_connect_done(struct tevent_req *subreq); -static void wb_trans_done(struct tevent_req *subreq); -static void wb_trans_retry_wait_done(struct tevent_req *subreq); - -struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct wb_context *wb_ctx, bool need_priv, - struct winbindd_request *wb_req) -{ - struct tevent_req *req; - struct wb_trans_state *state; - - req = tevent_req_create(mem_ctx, &state, struct wb_trans_state); - if (req == NULL) { - return NULL; - } - state->wb_ctx = wb_ctx; - state->ev = ev; - state->wb_req = wb_req; - state->need_priv = need_priv; - - if (!tevent_queue_add(wb_ctx->queue, ev, req, wb_trans_trigger, - NULL)) { - tevent_req_nomem(NULL, req); - return tevent_req_post(req, ev); - } - return req; -} - -static void wb_trans_trigger(struct tevent_req *req, void *private_data) -{ - struct wb_trans_state *state = tevent_req_data( - req, struct wb_trans_state); - struct tevent_req *subreq; - - if ((state->wb_ctx->fd != -1) && closed_fd(state->wb_ctx->fd)) { - close(state->wb_ctx->fd); - state->wb_ctx->fd = -1; - } - - if ((state->wb_ctx->fd == -1) - || (state->need_priv && !state->wb_ctx->is_priv)) { - subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, - state->need_priv); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_trans_connect_done, req); - return; - } - - state->wb_req->pid = getpid(); - - subreq = wb_simple_trans_send(state, state->ev, NULL, - state->wb_ctx->fd, state->wb_req); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_trans_done, req); -} - -static bool wb_trans_retry(struct tevent_req *req, - struct wb_trans_state *state, - wbcErr wbc_err) -{ - struct tevent_req *subreq; - - if (WBC_ERROR_IS_OK(wbc_err)) { - return false; - } - - if (wbc_err == WBC_ERR_WINBIND_NOT_AVAILABLE) { - /* - * Winbind not around or we can't connect to the pipe. Fail - * immediately. - */ - tevent_req_error(req, wbc_err); - return true; - } - - /* - * The transfer as such failed, retry after one second - */ - - if (state->wb_ctx->fd != -1) { - close(state->wb_ctx->fd); - state->wb_ctx->fd = -1; - } - - subreq = tevent_wakeup_send(state, state->ev, - timeval_current_ofs(1, 0)); - if (tevent_req_nomem(subreq, req)) { - return true; - } - tevent_req_set_callback(subreq, wb_trans_retry_wait_done, req); - return true; -} - -static void wb_trans_retry_wait_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_trans_state *state = tevent_req_data( - req, struct wb_trans_state); - bool ret; - - ret = tevent_wakeup_recv(subreq); - TALLOC_FREE(subreq); - if (!ret) { - tevent_req_error(req, WBC_ERR_UNKNOWN_FAILURE); - return; - } - - subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, - state->need_priv); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_trans_connect_done, req); -} - -static void wb_trans_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_trans_state *state = tevent_req_data( - req, struct wb_trans_state); - wbcErr wbc_err; - - wbc_err = wb_open_pipe_recv(subreq); - TALLOC_FREE(subreq); - - if (wb_trans_retry(req, state, wbc_err)) { - return; - } - - subreq = wb_simple_trans_send(state, state->ev, NULL, - state->wb_ctx->fd, state->wb_req); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_trans_done, req); -} - -static void wb_trans_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_trans_state *state = tevent_req_data( - req, struct wb_trans_state); - int ret, err; - - ret = wb_simple_trans_recv(subreq, state, &state->wb_resp, &err); - TALLOC_FREE(subreq); - if ((ret == -1) - && wb_trans_retry(req, state, map_wbc_err_from_errno(err))) { - return; - } - - tevent_req_done(req); -} - -wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presponse) -{ - struct wb_trans_state *state = tevent_req_data( - req, struct wb_trans_state); - wbcErr wbc_err; - - if (tevent_req_is_wbcerr(req, &wbc_err)) { - return wbc_err; - } - - *presponse = talloc_move(mem_ctx, &state->wb_resp); - return WBC_ERR_SUCCESS; -} 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, |