From 3a26c9f37f4cfa296de3bb23b97c27e5b20989f7 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 12 Oct 2003 20:48:30 +0000 Subject: make nt-time <-> unix-time functions nearly reversible (This used to be commit 98d60dc1c7027a50f720933eb8d6ffbfb4276fa5) --- source3/lib/time.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/lib/time.c b/source3/lib/time.c index 5309711a05..74ca56bdc5 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -318,8 +318,11 @@ time_t nt_time_to_unix(NTTIME *nt) /* now adjust by 369 years to make the secs since 1970 */ d -= TIME_FIXUP_CONSTANT; - if (!(l_time_min <= d && d <= l_time_max)) - return(0); + if (d <= l_time_min) + return (l_time_min); + + if (d >= l_time_max) + return (l_time_max); ret = (time_t)(d+0.5); -- cgit From 447fa1f2242006cd002598bf8d944e63a824ff86 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 13 Oct 2003 14:06:27 +0000 Subject: make sure to use the escaped DN; patch from Guenther Deschner; bug 592 (This used to be commit fe6aa4a95181bb2ad4352710cfc7868918609274) --- source3/nsswitch/winbindd_ads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index ef3f0f8fc2..5d0f924d8f 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -364,7 +364,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, return False; } - asprintf(&ldap_exp, "(distinguishedName=%s)", dn); + asprintf(&ldap_exp, "(distinguishedName=%s)", escaped_dn); rc = ads_search_retry(ads, &res, ldap_exp, attrs); SAFE_FREE(ldap_exp); SAFE_FREE(escaped_dn); -- cgit From 0bb70fe0b43fa9e9615e405b12c2adbb4ff04594 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Mon, 13 Oct 2003 18:34:57 +0000 Subject: Pull my previous changes into head as well. (This used to be commit 96f1ce740a8ebca3861bb2006b11301236a6fdb2) --- source3/nsswitch/wb_common.c | 2 ++ source3/nsswitch/winbindd.c | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'source3') diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 79553e9e4f..468b532cbe 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -191,6 +191,8 @@ static int winbind_named_pipe_sock(const char *dir) if (connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { + DEBUG(10, ("error connecting to pipe socket: %s\n", + strerror(errno))); close(fd); return -1; } diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 6a0056f917..4f161604b5 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -479,6 +479,13 @@ static void client_write(struct winbindd_cli_state *state) int num_written; /* Write some data */ + /* + * The fancy calculation of data below allows us to handle the + * case where write (sys_write) does not write all the data we + * gave it. In that case, we will come back through here again + * because of the loop above us, and we want to pick up where + * we left off. + */ if (!state->write_extra_data) { -- cgit From 5733f731a911478492315af288c1a674ec038452 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 13 Oct 2003 21:26:10 +0000 Subject: So here it is a non-intrusive patch with my latest work on gums (the laternative to the current passdb). Currently it is run through a comatibility module in the passdb layer, with a subset of the functionality it may provide. It is still work in progress, but as someone asked me about it, and as it should make no difference to the normal code, I tought it was a good idea to put it into. It adds a dependency on perl. I know it is not very nice, but I'm sure we will work out a solution for that. As always blame me if I break something, but try to fix yourself, as I am busy-busy-busy :-) Simo. (This used to be commit 7b3c94b5cfc1a9ceb430613353a937345f2eda74) --- source3/Makefile.in | 25 +- source3/configure.in | 9 +- source3/include/genparser_samba.h | 5 + source3/include/gums.h | 172 +++--- source3/include/includes.h | 4 + source3/include/passdb.h | 77 ++- source3/include/tdbsam2.h | 107 +++- source3/lib/genparser.c | 5 +- source3/lib/genparser_samba.c | 18 + source3/nsswitch/wb_common.c | 2 - source3/param/loadparm.c | 4 + source3/passdb/pdb_guest.c | 15 + source3/passdb/pdb_xml.c | 18 +- source3/sam/gumm_tdb.c | 4 +- source3/sam/gums.c | 171 ++++-- source3/sam/gums_api.c | 1230 +++++++++++++++++-------------------- source3/sam/gums_helper.c | 591 ++++++------------ 17 files changed, 1208 insertions(+), 1249 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 4769604243..1d25058df6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -184,7 +184,8 @@ LIB_OBJ = lib/version.o lib/charcnv.o lib/debug.o lib/fault.o \ lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \ lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \ - lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o + lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o \ + lib/genparser.o lib/genparser_samba.o LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o @@ -282,11 +283,14 @@ RPC_CLIENT_OBJ = rpc_client/cli_pipe.o LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o +GUMS_OBJ = sam/gums.o sam/gums_api.o sam/gums_helper.o + PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ passdb/machine_sid.o passdb/util_sam_sid.o passdb/pdb_compat.o \ - passdb/privileges.o passdb/lookup_sid.o @PDB_STATIC@ + passdb/privileges.o passdb/lookup_sid.o @PDB_STATIC@ \ + $(GUMS_OBJ) @GUMS_STATIC@ XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o @@ -1304,14 +1308,15 @@ clean: delheaders python_clean # afterwards. proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ - client/client_proto.h utils/net_proto.h smbd/build_options.c + client/client_proto.h utils/net_proto.h smbd/build_options.c \ + include/tdbsam2_parse_info.h delheaders: @echo Removing prototype headers @rm -f include/proto.h include/build_env.h include/wrepld_proto.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ client/client_proto.h utils/net_proto.h \ - smbd/build_options.c + smbd/build_options.c include/tdbsam2_parse_info.h MKPROTO_SH = $(srcdir)/script/mkproto.sh @@ -1352,6 +1357,15 @@ utils/net_proto.h: -h _CLIENT_PROTO_H_ $(builddir)/utils/net_proto.h \ $(NET_OBJ1) +include/tdbsam2_parse_info.h: + @if test -n "$(PERL)"; then \ + cd $(srcdir) && @PERL@ -w script/genstruct.pl \ + -o include/tdbsam2_parse_info.h $(CC) -E -O2 -g \ + include/tdbsam2.h; \ + else \ + echo Unable to build $@, continuing; \ + fi + # "make headers" or "make proto" calls a subshell because we need to # make sure these commands are executed in sequence even for a # parallel make. @@ -1364,7 +1378,8 @@ headers: $(MAKE) nsswitch/winbindd_proto.h; \ $(MAKE) web/swat_proto.h; \ $(MAKE) client/client_proto.h; \ - $(MAKE) utils/net_proto.h + $(MAKE) utils/net_proto.h; \ + $(MAKE) include/tdbsam2_parse_info.h proto: headers diff --git a/source3/configure.in b/source3/configure.in index 1bb97460ac..5c5cfb2ee2 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -296,7 +296,7 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin pdb_gums gums_tdbsam2" dnl These are preferably build shared, and static if dlopen() is not available default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437" @@ -4072,6 +4072,7 @@ MODULE_pdb_guest=STATIC MODULE_rpc_spoolss=STATIC MODULE_rpc_srv=STATIC MODULE_idmap_tdb=STATIC +MODULE_gums_tdbsam2=STATIC AC_ARG_WITH(static-modules, [ --with-static-modules=MODULES Comma-seperated list of names of modules to statically link in], @@ -4107,7 +4108,11 @@ SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o, "bin/ldapsam.$SHLIBEXT", PDB, SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB) SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB) SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB) -SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o) +SMB_MODULE(pdb_gums, passdb/pdb_gums.o, "bin/gums.$SHLIBEXT", PDB) +SMB_SUBSYSTEM(PDB,passdb/pdb_interface.c) + +SMB_MODULE(gums_tdbsam2, sam/gums_tdbsam2.o, "bin/tdbsam2.$SHLIBEXT", GUMS) +SMB_SUBSYSTEM(GUMS) SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC) SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC) diff --git a/source3/include/genparser_samba.h b/source3/include/genparser_samba.h index 172ff2362c..213d51da87 100644 --- a/source3/include/genparser_samba.h +++ b/source3/include/genparser_samba.h @@ -55,4 +55,9 @@ const struct parse_struct pinfo_luid_attr_info[] = { {"luid", 1, sizeof(LUID), offsetof(struct LUID_ATTR, luid), 0, NULL, 0, gen_dump_LUID, gen_parse_LUID}, {NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; +const struct parse_struct pinfo_data_blob_info[] = { +{"length", 0, sizeof(int), offsetof(DATA_BLOB, length), 0, NULL, 0, gen_dump_int, gen_parse_int}, +{"data", 1, sizeof(char), offsetof(DATA_BLOB, data), 0, "length", 0, gen_dump_char, gen_parse_char}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + #endif /* _GENPARSER_SAMBA_H */ diff --git a/source3/include/gums.h b/source3/include/gums.h index 789acc269f..9ce2ec4e56 100644 --- a/source3/include/gums.h +++ b/source3/include/gums.h @@ -24,14 +24,60 @@ #define GUMS_VERSION_MAJOR 0 #define GUMS_VERSION_MINOR 1 #define GUMS_OBJECT_VERSION 1 +#define GUMS_INTERFACE_VERSION 1 -#define GUMS_OBJ_DOMAIN 1 -#define GUMS_OBJ_NORMAL_USER 2 -#define GUMS_OBJ_GROUP 3 -#define GUMS_OBJ_ALIAS 4 -#define GUMS_OBJ_WORKSTATION_TRUST 5 -#define GUMS_OBJ_SERVER_TRUST 6 -#define GUMS_OBJ_DOMAIN_TRUST 7 +#define GUMS_OBJ_DOMAIN 0x10 +#define GUMS_OBJ_NORMAL_USER 0x20 +#define GUMS_OBJ_GROUP 0x30 +#define GUMS_OBJ_ALIAS 0x31 +#define GUMS_OBJ_PRIVILEGE 0x40 + +/* define value types */ +#define GUMS_SET_PRIMARY_GROUP 0x1 +#define GUMS_SET_SEC_DESC 0x2 + +#define GUMS_SET_NAME 0x10 +#define GUMS_SET_DESCRIPTION 0x11 +#define GUMS_SET_FULL_NAME 0x12 + +/* user specific type values */ +#define GUMS_SET_LOGON_TIME 0x20 +#define GUMS_SET_LOGOFF_TIME 0x21 +#define GUMS_SET_KICKOFF_TIME 0x23 +#define GUMS_SET_PASS_LAST_SET_TIME 0x24 +#define GUMS_SET_PASS_CAN_CHANGE_TIME 0x25 +#define GUMS_SET_PASS_MUST_CHANGE_TIME 0x26 + + +#define GUMS_SET_HOME_DIRECTORY 0x31 +#define GUMS_SET_DRIVE 0x32 +#define GUMS_SET_LOGON_SCRIPT 0x33 +#define GUMS_SET_PROFILE_PATH 0x34 +#define GUMS_SET_WORKSTATIONS 0x35 +#define GUMS_SET_UNKNOWN_STRING 0x36 +#define GUMS_SET_MUNGED_DIAL 0x37 + +#define GUMS_SET_LM_PASSWORD 0x40 +#define GUMS_SET_NT_PASSWORD 0x41 +#define GUMS_SET_PLAINTEXT_PASSWORD 0x42 +#define GUMS_SET_UNKNOWN_3 0x43 +#define GUMS_SET_LOGON_DIVS 0x44 +#define GUMS_SET_HOURS_LEN 0x45 +#define GUMS_SET_HOURS 0x46 +#define GUMS_SET_BAD_PASSWORD_COUNT 0x47 +#define GUMS_SET_LOGON_COUNT 0x48 +#define GUMS_SET_UNKNOWN_6 0x49 + +#define GUMS_SET_MUST_CHANGE_PASS 0x50 +#define GUMS_SET_CANNOT_CHANGE_PASS 0x51 +#define GUMS_SET_PASS_NEVER_EXPIRE 0x52 +#define GUMS_SET_ACCOUNT_DISABLED 0x53 +#define GUMS_SET_ACCOUNT_LOCKOUT 0x54 + +/*group specific type values */ +#define GUMS_ADD_SID_LIST 0x60 +#define GUMS_DEL_SID_LIST 0x61 +#define GUMS_SET_SID_LIST 0x62 typedef struct gums_user { @@ -52,17 +98,18 @@ typedef struct gums_user char *workstations; /* login from workstations string */ char *unknown_str; /* don't know what this is, yet. */ char *munged_dial; /* munged path name and dial-back tel number */ - + DATA_BLOB lm_pw; /* .data is Null if no password */ DATA_BLOB nt_pw; /* .data is Null if no password */ - - uint32 unknown_3; /* 0x00ff ffff */ - + + uint16 acct_ctrl; /* account type & status flags */ uint16 logon_divs; /* 168 - number of hours in a week */ uint32 hours_len; /* normally 21 bytes */ uint8 *hours; - - uint32 unknown_5; /* 0x0002 0000 */ + + uint16 bad_password_count; /* 0 */ + uint16 logon_count; /* 0 */ + uint32 unknown_3; /* 0x00ff ffff */ uint32 unknown_6; /* 0x0000 04ec */ } GUMS_USER; @@ -70,7 +117,7 @@ typedef struct gums_user typedef struct gums_group { uint32 count; /* Number of SIDs */ - DOM_SID **members; /* SID array */ + DOM_SID *members; /* SID array */ } GUMS_GROUP; @@ -80,10 +127,20 @@ typedef struct gums_domain } GUMS_DOMAIN; +typedef struct gums_privilege +{ + LUID_ATTR *privilege; /* Privilege Type */ + + uint32 count; + DOM_SID *members; + +} GUMS_PRIVILEGE; + union gums_obj_p { GUMS_USER *user; GUMS_GROUP *group; GUMS_DOMAIN *domain; + GUMS_PRIVILEGE *priv; }; typedef struct gums_object @@ -118,47 +175,47 @@ typedef struct gums_commit_set uint32 type; /* Object type */ DOM_SID sid; /* Object Sid */ uint32 count; /* number of changes */ - GUMS_DATA_SET **data; + GUMS_DATA_SET *data; } GUMS_COMMIT_SET; -typedef struct gums_privilege +typedef struct gums_priv_commit_set { TALLOC_CTX *mem_ctx; - uint32 type; /* Object Type */ - uint32 version; /* Object Version */ - uint32 seq_num; /* Object Sequence Number */ - - LUID_ATTR *privilege; /* Privilege Type */ - char *name; /* Object Name */ - char *description; /* Object Description */ + uint32 type; /* Object type */ + char *name; /* Object Sid */ + uint32 count; /* number of changes */ + GUMS_DATA_SET *data; - uint32 count; - DOM_SID **members; - -} GUMS_PRIVILEGE; +} GUMS_PRIV_COMMIT_SET; typedef struct gums_functions { + /* module data */ + TALLOC_CTX *mem_ctx; + char *name; + void *private_data; + void (*free_private_data)(void **); + /* Generic object functions */ - NTSTATUS (*get_domain_sid) (DOM_SID **sid, const char* name); + NTSTATUS (*get_domain_sid) (DOM_SID *sid, const char* name); NTSTATUS (*set_domain_sid) (const DOM_SID *sid); NTSTATUS (*get_sequence_number) (void); - NTSTATUS (*new_object) (DOM_SID **sid, const char *name, const int obj_type); + NTSTATUS (*new_object) (DOM_SID *sid, const char *name, const int obj_type); NTSTATUS (*delete_object) (const DOM_SID *sid); NTSTATUS (*get_object_from_sid) (GUMS_OBJECT **object, const DOM_SID *sid, const int obj_type); - NTSTATUS (*get_object_from_name) (GUMS_OBJECT **object, const char *name, const int onj_type); + NTSTATUS (*get_object_from_name) (GUMS_OBJECT **object, const char *name, const int obj_type); /* This function is used to get the list of all objects changed since b_time, it is used to support PDC<->BDC synchronization */ NTSTATUS (*get_updated_objects) (GUMS_OBJECT **objects, const NTTIME base_time); - NTSTATUS (*enumerate_objects_start) (void *handle, const DOM_SID *sid, const int obj_type); + NTSTATUS (*enumerate_objects_start) (void **handle, const DOM_SID *sid, const int obj_type); NTSTATUS (*enumerate_objects_get_next) (GUMS_OBJECT **object, void *handle); NTSTATUS (*enumerate_objects_stop) (void *handle); @@ -167,7 +224,7 @@ typedef struct gums_functions NTSTATUS (*set_object) (const GUMS_OBJECT *object); /* set object values function */ - NTSTATUS (*set_object_values) (DOM_SID *sid, uint32 count, GUMS_DATA_SET **data_set); + NTSTATUS (*set_object_values) (DOM_SID *sid, uint32 count, GUMS_DATA_SET *data_set); /* Group related functions */ NTSTATUS (*add_members_to_group) (const DOM_SID *group, const DOM_SID **members); @@ -191,50 +248,15 @@ typedef struct gums_functions } GUMS_FUNCTIONS; -/* define value types */ -#define GUMS_SET_PRIMARY_GROUP 0x1 -#define GUMS_SET_SEC_DESC 0x2 - -#define GUMS_SET_NAME 0x10 -#define GUMS_SET_DESCRIPTION 0x11 -#define GUMS_SET_FULL_NAME 0x12 +typedef NTSTATUS (*gums_init_function)( + struct gums_functions *, + const char *); -/* user specific type values */ -#define GUMS_SET_LOGON_TIME 0x20 -#define GUMS_SET_LOGOFF_TIME 0x21 -#define GUMS_SET_KICKOFF_TIME 0x23 -#define GUMS_SET_PASS_LAST_SET_TIME 0x24 -#define GUMS_SET_PASS_CAN_CHANGE_TIME 0x25 -#define GUMS_SET_PASS_MUST_CHANGE_TIME 0x26 +struct gums_init_function_entry { - -#define GUMS_SET_HOME_DIRECTORY 0x31 -#define GUMS_SET_DRIVE 0x32 -#define GUMS_SET_LOGON_SCRIPT 0x33 -#define GUMS_SET_PROFILE_PATH 0x34 -#define GUMS_SET_WORKSTATIONS 0x35 -#define GUMS_SET_UNKNOWN_STRING 0x36 -#define GUMS_SET_MUNGED_DIAL 0x37 - -#define GUMS_SET_LM_PASSWORD 0x40 -#define GUMS_SET_NT_PASSWORD 0x41 -#define GUMS_SET_PLAINTEXT_PASSWORD 0x42 -#define GUMS_SET_UNKNOWN_3 0x43 -#define GUMS_SET_LOGON_DIVS 0x44 -#define GUMS_SET_HOURS_LEN 0x45 -#define GUMS_SET_HOURS 0x46 -#define GUMS_SET_UNKNOWN_5 0x47 -#define GUMS_SET_UNKNOWN_6 0x48 - -#define GUMS_SET_MUST_CHANGE_PASS 0x50 -#define GUMS_SET_CANNOT_CHANGE_PASS 0x51 -#define GUMS_SET_PASS_NEVER_EXPIRE 0x52 -#define GUMS_SET_ACCOUNT_DISABLED 0x53 -#define GUMS_SET_ACCOUNT_LOCKOUT 0x54 - -/*group specific type values */ -#define GUMS_ADD_SID_LIST 0x60 -#define GUMS_DEL_SID_LIST 0x61 -#define GUMS_SET_SID_LIST 0x62 + const char *name; + gums_init_function init_fn; + struct gums_init_function_entry *prev, *next; +}; #endif /* _GUMS_H */ diff --git a/source3/include/includes.h b/source3/include/includes.h index 29bb53980f..452b489547 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -806,6 +806,10 @@ extern int errno; #include "rpc_secdes.h" +#include "genparser.h" + +#include "gums.h" + #include "nt_printing.h" #include "msdfs.h" diff --git a/source3/include/passdb.h b/source3/include/passdb.h index a4b2bcff3f..cd9c57a991 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -177,6 +177,15 @@ typedef struct sam_group { } SAM_GROUP; +typedef struct _GROUP_INFO { + struct pdb_methods *methods; + DOM_SID sid; + enum SID_NAME_USE sid_name_use; + fstring nt_name; + fstring comment; +} GROUP_INFO; + + /***************************************************************** Functions to be implemented by the new (v2) passdb API ****************************************************************/ @@ -192,26 +201,28 @@ typedef struct pdb_context { struct pdb_methods *pdb_methods; struct pdb_methods *pwent_methods; - + /* These functions are wrappers for the functions listed above. They may do extra things like re-reading a SAM_ACCOUNT on update */ NTSTATUS (*pdb_setsampwent)(struct pdb_context *, BOOL update); - + void (*pdb_endsampwent)(struct pdb_context *); - + NTSTATUS (*pdb_getsampwent)(struct pdb_context *, SAM_ACCOUNT *user); - + NTSTATUS (*pdb_getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username); - + NTSTATUS (*pdb_getsampwsid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const DOM_SID *sid); NTSTATUS (*pdb_add_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass); - + NTSTATUS (*pdb_update_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass); - + NTSTATUS (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username); + /* group mapping functions: to be removed */ + NTSTATUS (*pdb_getgrsid)(struct pdb_context *context, GROUP_MAP *map, DOM_SID sid); NTSTATUS (*pdb_getgrgid)(struct pdb_context *context, GROUP_MAP *map, gid_t gid); @@ -232,6 +243,30 @@ typedef struct pdb_context GROUP_MAP **rmap, int *num_entries, BOOL unix_only); + /* group functions */ + + NTSTATUS (*pdb_get_group_info_by_sid)(struct pdb_context *context, GROUP_INFO *info, const DOM_SID *group); + + NTSTATUS (*pdb_get_group_list)(struct pdb_context *context, GROUP_INFO **info, const enum SID_NAME_USE sid_name_use, int *num_groups); + + NTSTATUS (*pdb_get_group_sids)(struct pdb_context *context, const DOM_SID *group, DOM_SID **members, int *num_members); + + NTSTATUS (*pdb_add_group)(struct pdb_context *context, const SAM_GROUP *group); + + NTSTATUS (*pdb_update_group)(struct pdb_context *context, const SAM_GROUP *group); + + NTSTATUS (*pdb_delete_group)(struct pdb_context *context, const DOM_SID *group); + + NTSTATUS (*pdb_add_sid_to_group)(struct pdb_context *context, const DOM_SID *group, const DOM_SID *member); + + NTSTATUS (*pdb_remove_sid_from_group)(struct pdb_context *context, const DOM_SID *group, const DOM_SID *member); + + NTSTATUS (*pdb_get_group_info_by_name)(struct pdb_context *context, GROUP_INFO *info, const char *name); + + NTSTATUS (*pdb_get_group_info_by_nt_name)(struct pdb_context *context, GROUP_INFO *info, const char *nt_name); + + NTSTATUS (*pdb_get_group_uids)(struct pdb_context *context, const DOM_SID *group, uid_t **members, int *num_members); + void (*free_fn)(struct pdb_context **); TALLOC_CTX *mem_ctx; @@ -262,7 +297,9 @@ typedef struct pdb_methods NTSTATUS (*update_sam_account)(struct pdb_methods *, SAM_ACCOUNT *sampass); NTSTATUS (*delete_sam_account)(struct pdb_methods *, SAM_ACCOUNT *username); - + + /* group mapping functions: to be removed */ + NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, DOM_SID sid); NTSTATUS (*getgrgid)(struct pdb_methods *methods, GROUP_MAP *map, gid_t gid); @@ -283,6 +320,30 @@ typedef struct pdb_methods GROUP_MAP **rmap, int *num_entries, BOOL unix_only); + /* group functions */ + + NTSTATUS (*get_group_info_by_sid)(struct pdb_methods *methods, GROUP_INFO *info, const DOM_SID *group); + + NTSTATUS (*get_group_list)(struct pdb_methods *methods, GROUP_INFO **info, const enum SID_NAME_USE sid_name_use, int *num_groups); + + NTSTATUS (*get_group_sids)(struct pdb_methods *methods, const DOM_SID *group, DOM_SID **members, int *num_members); + + NTSTATUS (*add_group)(struct pdb_methods *methods, const SAM_GROUP *group); + + NTSTATUS (*update_group)(struct pdb_methods *methods, const SAM_GROUP *group); + + NTSTATUS (*delete_group)(struct pdb_methods *methods, const DOM_SID *group); + + NTSTATUS (*add_sid_to_group)(struct pdb_methods *methods, const DOM_SID *group, const DOM_SID *member); + + NTSTATUS (*remove_sid_from_group)(struct pdb_methods *methods, const DOM_SID *group, const DOM_SID *member); + + NTSTATUS (*get_group_info_by_name)(struct pdb_methods *methods, GROUP_INFO *info, const char *name); + + NTSTATUS (*get_group_info_by_nt_name)(struct pdb_methods *methods, GROUP_INFO *info, const char *nt_name); + + NTSTATUS (*get_group_uids)(struct pdb_methods *methods, const DOM_SID *group, uid_t **members, int *num_members); + void *private_data; /* Private data of some kind */ void (*free_private_data)(void **); diff --git a/source3/include/tdbsam2.h b/source3/include/tdbsam2.h index 047b4e7c90..b99e16586b 100644 --- a/source3/include/tdbsam2.h +++ b/source3/include/tdbsam2.h @@ -20,33 +20,46 @@ /* ALL strings assumes UTF8 as encoding */ -GENSTRUCT struct tdbsam2_domain_data { - uint32 xcounter; /* counter to be updated at any change */ +#ifndef TDBSAM2_H +#define TDBSAM2_H - SEC_DESC *sec_desc; /* Security Descriptor */ - DOM_SID *dom_sid; /* The Domain SID */ - char *name; _NULLTERM /* NT Domain Name */ - char *description; _NULLTERM /* Descritpion (Gecos) */ +/* IMPORTANT: these structures must follow closely the GUMS_OBJECTs + * structures as they will be casted over !! + * the GUMS_OBJECT union is unrolled here into four tdbsam2 + * objects cause genstruct is not able to follow arbitrary unions */ +GENSTRUCT struct domain_sub_structure +{ uint32 next_rid; /* The Next free RID */ }; -GENSTRUCT struct tdbsam2_user_data { +GENSTRUCT struct tdbsam2_domain_data +{ + TALLOC_CTX *mem_ctx; + + uint32 type; + uint32 version; uint32 xcounter; /* counter to be updated at any change */ SEC_DESC *sec_desc; /* Security Descriptor */ - DOM_SID *user_sid; /* The User SID */ - char *name; _NULLTERM /* NT User Name */ + + DOM_SID *dom_sid; /* The Domain SID */ + char *name; _NULLTERM /* NT Domain Name */ char *description; _NULLTERM /* Descritpion (Gecos) */ + struct domain_sub_structure *dss; +}; + +GENSTRUCT struct user_sub_structure +{ DOM_SID *group_sid; /* The Primary Group SID */ - NTTIME *logon_time; - NTTIME *logoff_time; - NTTIME *kickoff_time; - NTTIME *pass_last_set_time; - NTTIME *pass_can_change_time; - NTTIME *pass_must_change_time; + NTTIME logon_time; + NTTIME logoff_time; + NTTIME kickoff_time; + NTTIME pass_last_set_time; + NTTIME pass_can_change_time; + NTTIME pass_must_change_time; char *full_name; _NULLTERM /* The Full Name */ char *home_dir; _NULLTERM /* Home Directory */ @@ -57,39 +70,81 @@ GENSTRUCT struct tdbsam2_user_data { char *unknown_str; _NULLTERM /* Guess ... Unknown */ char *munged_dial; _NULLTERM /* Callback Number */ - /* passwords are 16 byte leght, pointer is null if no password */ - uint8 *lm_pw_ptr; _LEN(16) /* Lanman hashed password */ - uint8 *nt_pw_ptr; _LEN(16) /* NT hashed password */ + DATA_BLOB lm_pw; /* .data is Null if no password */ + DATA_BLOB nt_pw; /* .data is Null if no password */ + uint16 acct_ctrl; /* account flags */ uint16 logon_divs; /* 168 - num of hours in a week */ uint32 hours_len; /* normally 21 */ uint8 *hours; _LEN(hours_len) /* normally 21 bytes (depends on hours_len) */ + uint16 bad_password_count; /* 0 */ + uint16 logon_count; /* 0 */ uint32 unknown_3; /* 0x00ff ffff */ - uint32 unknown_5; /* 0x0002 0000 */ uint32 unknown_6; /* 0x0000 04ec */ }; -GENSTRUCT struct tdbsam2_group_data { +GENSTRUCT struct tdbsam2_user_data +{ + TALLOC_CTX *mem_ctx; + + uint32 type; + uint32 version; uint32 xcounter; /* counter to be updated at any change */ SEC_DESC *sec_desc; /* Security Descriptor */ + + DOM_SID *user_sid; /* The User SID */ + char *name; _NULLTERM /* NT User Name */ + char *description; _NULLTERM /* Descritpion (Gecos) */ + + struct user_sub_structure *uss; +}; + +GENSTRUCT struct group_sub_structure +{ + uint32 count; /* number of sids */ + DOM_SID *members; _LEN(count) /* SID array */ +}; + +GENSTRUCT struct tdbsam2_group_data +{ + TALLOC_CTX *mem_ctx; + + uint32 type; + uint32 version; + uint32 xcounter; /* counter to be updated at any change */ + + SEC_DESC *sec_desc; /* Security Descriptor */ + DOM_SID *group_sid; /* The Group SID */ char *name; _NULLTERM /* NT Group Name */ char *description; _NULLTERM /* Descritpion (Gecos) */ + struct group_sub_structure *gss; +}; + +GENSTRUCT struct priv_sub_structure +{ + LUID_ATTR *privilege; /* Privilege */ + uint32 count; /* number of sids */ - DOM_SID **members; _LEN(count) /* SID array */ + DOM_SID *members; _LEN(count) /* SID array */ }; -GENSTRUCT struct tdbsam2_privilege_data { +GENSTRUCT struct tdbsam2_priv_data +{ + TALLOC_CTX *mem_ctx; + + uint32 type; + uint32 version; uint32 xcounter; /* counter to be updated at any change */ - LUID_ATTR *privilege; /* Privilege */ - char *name; _NULLTERM /* NT User Name */ + DOM_SID *null_sid; + char *name; _NULLTERM /* Privilege Name */ char *description; _NULLTERM /* Descritpion (Gecos) */ - uint32 count; /* number of sids */ - DOM_SID **members; _LEN(count) /* SID array */ + struct priv_sub_structure *pss; }; +#endif /* TDBSAM2_H */ diff --git a/source3/lib/genparser.c b/source3/lib/genparser.c index 233050b432..7476b5d0af 100644 --- a/source3/lib/genparser.c +++ b/source3/lib/genparser.c @@ -256,7 +256,6 @@ static int gen_dump_array(TALLOC_CTX *mem_ctx, addstr(mem_ctx, p, "}\n")) { return -1; } - free(s); return 0; } @@ -673,7 +672,7 @@ int gen_parse(TALLOC_CTX *mem_ctx, const struct parse_struct *pinfo, char *data, { char *str, *s0; - s0 = strdup(s); + s0 = talloc_strdup(mem_ctx, s); str = s0; while (*str) { @@ -706,12 +705,10 @@ int gen_parse(TALLOC_CTX *mem_ctx, const struct parse_struct *pinfo, char *data, *str++ = 0; if (gen_parse_one(mem_ctx, pinfo, name, data, value) != 0) { - free(s0); return -1; } } - free(s0); return 0; } diff --git a/source3/lib/genparser_samba.c b/source3/lib/genparser_samba.c index bece587747..7eabf5a56e 100644 --- a/source3/lib/genparser_samba.c +++ b/source3/lib/genparser_samba.c @@ -118,7 +118,16 @@ int gen_parse_LUID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) return 0; } +int gen_parse_DATA_BLOB(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + return gen_parse_struct(mem_ctx, pinfo_data_blob_info, ptr, str); +} +int gen_parse_TALLOC_CTX(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + (TALLOC_CTX *)ptr = NULL; + return 0; +} /* DUMP functions */ @@ -198,3 +207,12 @@ int gen_dump_LUID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, return addshort(mem_ctx, p, "%u,%u", high, low); } +int gen_dump_DATA_BLOB(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return gen_dump_struct(mem_ctx, pinfo_data_blob_info, p, ptr, indent); +} + +int gen_dump_TALLOC_CTX(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "TALLOC_CTX"); +} diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 468b532cbe..79553e9e4f 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -191,8 +191,6 @@ static int winbind_named_pipe_sock(const char *dir) if (connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { - DEBUG(10, ("error connecting to pipe socket: %s\n", - strerror(errno))); close(fd); return -1; } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 5a5ac4a2cc..e6705d8c7b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -122,6 +122,7 @@ typedef struct char *szSMBPasswdFile; char *szPrivateDir; char **szPassdbBackend; + char *szGumsBackend; char **szPreloadModules; char *szPasswordServer; char *szSocketOptions; @@ -791,6 +792,7 @@ static struct parm_struct parm_table[] = { {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + {"gums backend", P_STRING, P_GLOBAL, &Globals.szGumsBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, @@ -1453,6 +1455,7 @@ static void init_globals(void) #else Globals.szPassdbBackend = str_list_make("smbpasswd", NULL); #endif /* WITH_LDAP_SAMCONFIG */ + string_set(&Globals.szGumsBackend, "tdbsam2"); string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapFilter, "(uid=%u)"); @@ -1651,6 +1654,7 @@ FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName) static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion) FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases) FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend) +FN_GLOBAL_STRING(lp_gums_backend, &Globals.szGumsBackend) FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules) FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction) FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript) diff --git a/source3/passdb/pdb_guest.c b/source3/passdb/pdb_guest.c index fa29657edc..3cd6efb38a 100644 --- a/source3/passdb/pdb_guest.c +++ b/source3/passdb/pdb_guest.c @@ -141,6 +141,21 @@ NTSTATUS pdb_init_guestsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, c (*pdb_method)->delete_group_mapping_entry = pdb_nop_delete_group_mapping_entry; (*pdb_method)->enum_group_mapping = pdb_nop_enum_group_mapping; + /* we do not handle groups in guest backend */ +/* FIXME + (*pdb_method)->get_group_info_by_sid = pdb_nop_get_group_info_by_sid; + (*pdb_method)->get_group_list = pdb_nop_get_group_list; + (*pdb_method)->get_group_sids = pdb_nop_get_group_sids; + (*pdb_method)->add_group = pdb_nop_add_group; + (*pdb_method)->update_group = pdb_nop_update_group; + (*pdb_method)->delete_group = pdb_nop_delete_group; + (*pdb_method)->add_sid_to_group = pdb_nop_add_sid_to_group; + (*pdb_method)->remove_sid_from_group = pdb_nop_remove_sid_from_group; + (*pdb_method)->get_group_info_by_name = pdb_nop_get_group_info_by_name; + (*pdb_method)->get_group_info_by_nt_name = pdb_nop_get_group_info_by_nt_name; + (*pdb_method)->get_group_uids = pdb_nop_get_group_uids; +*/ + /* There's not very much to initialise here */ return NT_STATUS_OK; diff --git a/source3/passdb/pdb_xml.c b/source3/passdb/pdb_xml.c index 29922bca4f..19998a6655 100644 --- a/source3/passdb/pdb_xml.c +++ b/source3/passdb/pdb_xml.c @@ -540,13 +540,17 @@ static NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method (*pdb_method)->getsampwsid = NULL; (*pdb_method)->update_sam_account = NULL; (*pdb_method)->delete_sam_account = NULL; - (*pdb_method)->getgrsid = NULL; - (*pdb_method)->getgrgid = NULL; - (*pdb_method)->getgrnam = NULL; - (*pdb_method)->add_group_mapping_entry = NULL; - (*pdb_method)->update_group_mapping_entry = NULL; - (*pdb_method)->delete_group_mapping_entry = NULL; - (*pdb_method)->enum_group_mapping = NULL; + (*pdb_method)->get_group_info_by_sid = NULL; + (*pdb_method)->get_group_list = NULL; + (*pdb_method)->get_group_sids = NULL; + (*pdb_method)->add_group = NULL; + (*pdb_method)->update_group = NULL; + (*pdb_method)->delete_group = NULL; + (*pdb_method)->add_sid_to_group = NULL; + (*pdb_method)->remove_sid_from_group = NULL; + (*pdb_method)->get_group_info_by_name = NULL; + (*pdb_method)->get_group_info_by_nt_name = NULL; + (*pdb_method)->get_group_uids = NULL; data = talloc(pdb_context->mem_ctx, sizeof(pdb_xml)); data->location = talloc_strdup(pdb_context->mem_ctx, (location ? location : "passdb.xml")); diff --git a/source3/sam/gumm_tdb.c b/source3/sam/gumm_tdb.c index 5da2407faa..2623180afb 100644 --- a/source3/sam/gumm_tdb.c +++ b/source3/sam/gumm_tdb.c @@ -464,7 +464,7 @@ static NTSTATUS user_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_us SET_OR_FAIL(gums_set_user_hours(*object, userdata->hours), error); SET_OR_FAIL(gums_set_user_unknown_3(*object, userdata->unknown_3), error); - SET_OR_FAIL(gums_set_user_unknown_5(*object, userdata->unknown_5), error); + SET_OR_FAIL(gums_set_user_bad_password_count(*object, userdata->bad_password_count), error); SET_OR_FAIL(gums_set_user_unknown_6(*object, userdata->unknown_6), error); SET_OR_FAIL(gums_set_user_logon_time(*object, *(userdata->logon_time)), error); @@ -750,7 +750,7 @@ static NTSTATUS tdbsam2_new_object(DOM_SID *sid, const char *name, const int obj obj.data.user->hours = &defhours; obj.data.user->unknown_3 = 0x00ffffff; - obj.data.user->unknown_5 = 0x00020000; + obj.data.user->bad_password_count = 0x00020000; obj.data.user->unknown_6 = 0x000004ec; break; diff --git a/source3/sam/gums.c b/source3/sam/gums.c index a118740637..ab374b9342 100644 --- a/source3/sam/gums.c +++ b/source3/sam/gums.c @@ -20,8 +20,8 @@ #include "includes.h" -/*#undef DBGC_CLASS -#define DBGC_CLASS DBGC_GUMS*/ +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_SAM #define GMV_MAJOR 0 #define GMV_MINOR 1 @@ -56,8 +56,7 @@ #define PRIV_ALL 255 -GUMS_FUNCTIONS *gums_storage; -static void *dl_handle; +static GUMS_FUNCTIONS *gums_backend = NULL; static PRIVS gums_privs[] = { {PRIV_NONE, "no_privs", "No privilege"}, /* this one MUST be first */ @@ -90,72 +89,146 @@ static PRIVS gums_privs[] = { {PRIV_ALL, "SaAllPrivs", "All Privileges"} }; -NTSTATUS gums_init(const char *module_name) +static struct gums_init_function_entry *backends = NULL; + +static void lazy_initialize_gums(void) { - int (*module_version)(int); - NTSTATUS (*module_init)(); -/* gums_module_init module_init;*/ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + static BOOL initialized = False; + + if (initialized) + return; - DEBUG(5, ("Opening gums module %s\n", module_name)); - dl_handle = sys_dlopen(module_name, RTLD_NOW); - if (!dl_handle) { - DEBUG(0, ("ERROR: Failed to load gums module %s, error: %s\n", module_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } + static_init_gums; + initialized = True; +} - module_version = sys_dlsym(dl_handle, "gumm_version"); - if (!module_version) { - DEBUG(0, ("ERROR: Failed to find gums module version!\n")); - goto error; - } +static struct gums_init_function_entry *gums_find_backend_entry(const char *name); + +NTSTATUS gums_register_module(int version, const char *name, gums_init_function init_fn) +{ + struct gums_init_function_entry *entry = backends; + + if (version != GUMS_INTERFACE_VERSION) { + DEBUG(0,("Can't register gums backend!\n" + "You tried to register a gums module with" + "GUMS_INTERFACE_VERSION %d, while this version" + "of samba uses version %d\n", version, + GUMS_INTERFACE_VERSION)); - if (module_version(GMV_MAJOR) != GUMS_VERSION_MAJOR) { - DEBUG(0, ("ERROR: Module's major version does not match gums version!\n")); - goto error; + return NT_STATUS_OBJECT_TYPE_MISMATCH; } - if (module_version(GMV_MINOR) != GUMS_VERSION_MINOR) { - DEBUG(1, ("WARNING: Module's minor version does not match gums version!\n")); + if (!name || !init_fn) { + return NT_STATUS_INVALID_PARAMETER; } - module_init = sys_dlsym(dl_handle, "gumm_init"); - if (!module_init) { - DEBUG(0, ("ERROR: Failed to find gums module's init function!\n")); - goto error; + DEBUG(5,("Attempting to register gums backend %s\n", name)); + + /* Check for duplicates */ + if (gums_find_backend_entry(name)) { + DEBUG(0,("There already is a gums backend registered" + "with the name %s!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; } - DEBUG(5, ("Initializing module %s\n", module_name)); + entry = smb_xmalloc(sizeof(struct gums_init_function_entry)); + entry->name = smb_xstrdup(name); + entry->init_fn = init_fn; - ret = module_init(&gums_storage); - goto done; + DLIST_ADD(backends, entry); + DEBUG(5,("Successfully added gums backend '%s'\n", name)); + return NT_STATUS_OK; +} -error: - ret = NT_STATUS_UNSUCCESSFUL; - sys_dlclose(dl_handle); +static struct gums_init_function_entry *gums_find_backend_entry(const char *name) +{ + struct gums_init_function_entry *entry = backends; -done: - return ret; + while (entry) { + if (strcmp(entry->name, name) == 0) + return entry; + entry = entry->next; + } + + return NULL; } -NTSTATUS gums_unload(void) +NTSTATUS gums_setup_backend(const char *backend) { - NTSTATUS ret; - NTSTATUS (*module_finalize)(); - if (!dl_handle) - return NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *mem_ctx; + char *module_name = smb_xstrdup(backend); + char *p, *module_data = NULL; + struct gums_init_function_entry *entry; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + lazy_initialize_gums(); + + p = strchr(module_name, ':'); + if (p) { + *p = 0; + module_data = p+1; + trim_string(module_data, " ", " "); + } + + trim_string(module_name, " ", " "); - module_finalize = sys_dlsym(dl_handle, "gumm_finalize"); - if (!module_finalize) { - DEBUG(0, ("ERROR: Failed to find gums module's init function!\n")); - return NT_STATUS_UNSUCCESSFUL; + DEBUG(5,("Attempting to find a gums backend to match %s (%s)\n", backend, module_name)); + + entry = gums_find_backend_entry(module_name); + + /* Try to find a module that contains this module */ + if (!entry) { + DEBUG(2,("No builtin backend found, trying to load plugin\n")); + if(NT_STATUS_IS_OK(smb_probe_module("gums", module_name)) && !(entry = gums_find_backend_entry(module_name))) { + DEBUG(0,("Plugin is available, but doesn't register gums backend %s\n", module_name)); + SAFE_FREE(module_name); + return NT_STATUS_UNSUCCESSFUL; + } } - DEBUG(5, ("Finalizing module")); + /* No such backend found */ + if(!entry) { + DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name)); + SAFE_FREE(module_name); + return NT_STATUS_INVALID_PARAMETER; + } - ret = module_finalize(); - sys_dlclose(dl_handle); + DEBUG(5,("Found gums backend %s\n", module_name)); + /* free current functions structure if any */ + if (gums_backend) { + gums_backend->free_private_data(gums_backend->private_data); + talloc_destroy(gums_backend->mem_ctx); + gums_backend = NULL; + } + + /* allocate a new GUMS_FUNCTIONS structure and memory context */ + mem_ctx = talloc_init("gums_backend (%s)", module_name); + if (!mem_ctx) + return NT_STATUS_NO_MEMORY; + gums_backend = talloc(mem_ctx, sizeof(GUMS_FUNCTIONS)); + if (!gums_backend) + return NT_STATUS_NO_MEMORY; + gums_backend->mem_ctx = mem_ctx; + + /* init the requested backend module */ + if (NT_STATUS_IS_OK(ret = entry->init_fn(gums_backend, module_data))) { + DEBUG(5,("gums backend %s has a valid init\n", backend)); + } else { + DEBUG(0,("gums backend %s did not correctly init (error was %s)\n", backend, nt_errstr(ret))); + } + SAFE_FREE(module_name); return ret; } + +NTSTATUS get_gums_fns(GUMS_FUNCTIONS **fns) +{ + if (gums_backend != NULL) { + *fns = gums_backend; + return NT_STATUS_OK; + } + + DEBUG(2, ("get_gums_fns: unable to get gums functions! backend uninitialized?\n")); + return NT_STATUS_UNSUCCESSFUL; +} diff --git a/source3/sam/gums_api.c b/source3/sam/gums_api.c index 2e5dcd143a..17f7d33baa 100644 --- a/source3/sam/gums_api.c +++ b/source3/sam/gums_api.c @@ -20,195 +20,8 @@ #include "includes.h" - -/******************************************************************* - Create a SEC_ACL structure. -********************************************************************/ - -static SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) -{ - SEC_ACL *dst; - int i; - - if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) - return NULL; - - dst->revision = revision; - dst->num_aces = num_aces; - dst->size = SEC_ACL_HEADER_SIZE; - - /* Now we need to return a non-NULL address for the ace list even - if the number of aces required is zero. This is because there - is a distinct difference between a NULL ace and an ace with zero - entries in it. This is achieved by checking that num_aces is a - positive number. */ - - if ((num_aces) && - ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) - == NULL)) { - return NULL; - } - - for (i = 0; i < num_aces; i++) { - dst->ace[i] = ace_list[i]; /* Structure copy. */ - dst->size += ace_list[i].size; - } - - return dst; -} - - - -/******************************************************************* - Duplicate a SEC_ACL structure. -********************************************************************/ - -static SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) -{ - if(src == NULL) - return NULL; - - return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); -} - - - -/******************************************************************* - Creates a SEC_DESC structure -********************************************************************/ - -static SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, - DOM_SID *owner_sid, DOM_SID *grp_sid, - SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) -{ - SEC_DESC *dst; - uint32 offset = 0; - uint32 offset_sid = SEC_DESC_HEADER_SIZE; - uint32 offset_acl = 0; - - *sd_size = 0; - - if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) - return NULL; - - dst->revision = revision; - dst->type = SEC_DESC_SELF_RELATIVE; - - if (sacl) dst->type |= SEC_DESC_SACL_PRESENT; - if (dacl) dst->type |= SEC_DESC_DACL_PRESENT; - - dst->off_owner_sid = 0; - dst->off_grp_sid = 0; - dst->off_sacl = 0; - dst->off_dacl = 0; - - if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) - goto error_exit; - - if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) - goto error_exit; - - if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) - goto error_exit; - - if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) - goto error_exit; - - offset = 0; - - /* - * Work out the linearization sizes. - */ - if (dst->owner_sid != NULL) { - - if (offset == 0) - offset = SEC_DESC_HEADER_SIZE; - - offset += sid_size(dst->owner_sid); - } - - if (dst->grp_sid != NULL) { - - if (offset == 0) - offset = SEC_DESC_HEADER_SIZE; - - offset += sid_size(dst->grp_sid); - } - - if (dst->sacl != NULL) { - - offset_acl = SEC_DESC_HEADER_SIZE; - - dst->off_sacl = offset_acl; - offset_acl += dst->sacl->size; - offset += dst->sacl->size; - offset_sid += dst->sacl->size; - } - - if (dst->dacl != NULL) { - - if (offset_acl == 0) - offset_acl = SEC_DESC_HEADER_SIZE; - - dst->off_dacl = offset_acl; - offset_acl += dst->dacl->size; - offset += dst->dacl->size; - offset_sid += dst->dacl->size; - } - - *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset); - - if (dst->owner_sid != NULL) - dst->off_owner_sid = offset_sid; - - /* sid_size() returns 0 if the sid is NULL so this is ok */ - - if (dst->grp_sid != NULL) - dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid); - - return dst; - -error_exit: - - *sd_size = 0; - return NULL; -} - -/******************************************************************* - Duplicate a SEC_DESC structure. -********************************************************************/ - -static SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src) -{ - size_t dummy; - - if(src == NULL) - return NULL; - - return make_sec_desc( ctx, src->revision, - src->owner_sid, src->grp_sid, src->sacl, - src->dacl, &dummy); -} - - - - - - - -extern GUMS_FUNCTIONS *gums_storage; - /* Functions to get/set info from a GUMS object */ -NTSTATUS gums_get_object_type(uint32 *type, const GUMS_OBJECT *obj) -{ - if (!obj) - return NT_STATUS_INVALID_PARAMETER; - - *type = obj->type; - return NT_STATUS_OK; -} - NTSTATUS gums_create_object(GUMS_OBJECT **obj, uint32 type) { TALLOC_CTX *mem_ctx = talloc_init("gums_create_object"); @@ -222,6 +35,7 @@ NTSTATUS gums_create_object(GUMS_OBJECT **obj, uint32 type) switch(type) { case GUMS_OBJ_DOMAIN: + go->data.domain = (GUMS_DOMAIN *)talloc_zero(mem_ctx, sizeof(GUMS_DOMAIN)); break; /* @@ -238,6 +52,10 @@ NTSTATUS gums_create_object(GUMS_OBJECT **obj, uint32 type) go->data.group = (GUMS_GROUP *)talloc_zero(mem_ctx, sizeof(GUMS_GROUP)); break; + case GUMS_OBJ_PRIVILEGE: + go->data.priv = (GUMS_PRIVILEGE *)talloc_zero(mem_ctx, sizeof(GUMS_PRIVILEGE)); + break; + default: /* TODO: throw error */ ret = NT_STATUS_OBJECT_TYPE_MISMATCH; @@ -250,96 +68,170 @@ NTSTATUS gums_create_object(GUMS_OBJECT **obj, uint32 type) goto error; } + switch(type) { + case GUMS_OBJ_NORMAL_USER: + gums_set_user_acct_ctrl(go, ACB_NORMAL); + gums_set_user_hours(go, 0, NULL); + } + *obj = go; return NT_STATUS_OK; - + error: talloc_destroy(go->mem_ctx); *obj = NULL; return ret; } -NTSTATUS gums_get_object_seq_num(uint32 *version, const GUMS_OBJECT *obj) +NTSTATUS gums_destroy_object(GUMS_OBJECT **obj) { - if (!version || !obj) + if (!obj || !(*obj)) return NT_STATUS_INVALID_PARAMETER; - *version = obj->version; + if ((*obj)->mem_ctx) + talloc_destroy((*obj)->mem_ctx); + *obj = NULL; + return NT_STATUS_OK; } -NTSTATUS gums_set_object_seq_num(GUMS_OBJECT *obj, uint32 version) +void gums_reset_object(GUMS_OBJECT *go) +{ + go->seq_num = 0; + go->sid = NULL; + go->name = NULL; + go->description = NULL; + + switch(go->type) { + case GUMS_OBJ_DOMAIN: + memset(go->data.domain, 0, sizeof(GUMS_DOMAIN)); + break; + +/* + case GUMS_OBJ_WORKSTATION_TRUST: + case GUMS_OBJ_SERVER_TRUST: + case GUMS_OBJ_DOMAIN_TRUST: +*/ + case GUMS_OBJ_NORMAL_USER: + memset(go->data.user, 0, sizeof(GUMS_USER)); + gums_set_user_acct_ctrl(go, ACB_NORMAL); + break; + + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + memset(go->data.group, 0, sizeof(GUMS_GROUP)); + break; + + case GUMS_OBJ_PRIVILEGE: + memset(go->data.priv, 0, sizeof(GUMS_PRIVILEGE)); + break; + + default: + return; + } +} + +uint32 gums_get_object_type(const GUMS_OBJECT *obj) { if (!obj) - return NT_STATUS_INVALID_PARAMETER; + return 0; - obj->version = version; - return NT_STATUS_OK; + return obj->type; } -NTSTATUS gums_get_sec_desc(SEC_DESC **sec_desc, const GUMS_OBJECT *obj) +uint32 gums_get_object_seq_num(const GUMS_OBJECT *obj) { - if (!sec_desc || !obj) - return NT_STATUS_INVALID_PARAMETER; + if (!obj) + return 0; - *sec_desc = obj->sec_desc; - return NT_STATUS_OK; + return obj->seq_num; } -NTSTATUS gums_set_sec_desc(GUMS_OBJECT *obj, const SEC_DESC *sec_desc) +uint32 gums_get_object_version(const GUMS_OBJECT *obj) { - if (!obj || !sec_desc) - return NT_STATUS_INVALID_PARAMETER; + if (!obj) + return 0; - obj->sec_desc = dup_sec_desc(obj->mem_ctx, sec_desc); - if (!(obj->sec_desc)) return NT_STATUS_UNSUCCESSFUL; - return NT_STATUS_OK; + return obj->version; } -NTSTATUS gums_get_object_sid(DOM_SID **sid, const GUMS_OBJECT *obj) +const SEC_DESC *gums_get_sec_desc(const GUMS_OBJECT *obj) { - if (!sid || !obj) + if (!obj) + return NULL; + + return obj->sec_desc; +} + +const DOM_SID *gums_get_object_sid(const GUMS_OBJECT *obj) +{ + if (!obj) + return NULL; + + return obj->sid; +} + +const char *gums_get_object_name(const GUMS_OBJECT *obj) +{ + if (!obj) + return NULL; + + return obj->name; +} + +const char *gums_get_object_description(const GUMS_OBJECT *obj) +{ + if (!obj) + return NULL; + + return obj->description; +} + +NTSTATUS gums_set_object_seq_num(GUMS_OBJECT *obj, uint32 seq_num) +{ + if (!obj) return NT_STATUS_INVALID_PARAMETER; - *sid = obj->sid; + obj->seq_num = seq_num; return NT_STATUS_OK; } -NTSTATUS gums_set_object_sid(GUMS_OBJECT *obj, const DOM_SID *sid) +NTSTATUS gums_set_object_version(GUMS_OBJECT *obj, uint32 version) { - if (!obj || !sid) + if (!obj) return NT_STATUS_INVALID_PARAMETER; - obj->sid = sid_dup_talloc(obj->mem_ctx, sid); - if (!(obj->sid)) return NT_STATUS_UNSUCCESSFUL; + obj->version = version; return NT_STATUS_OK; } -NTSTATUS gums_get_object_name(char **name, const GUMS_OBJECT *obj) +NTSTATUS gums_set_sec_desc(GUMS_OBJECT *obj, const SEC_DESC *sec_desc) { - if (!name || !obj) + if (!obj || !sec_desc) return NT_STATUS_INVALID_PARAMETER; - *name = obj->name; + obj->sec_desc = dup_sec_desc(obj->mem_ctx, sec_desc); + if (!(obj->sec_desc)) return NT_STATUS_UNSUCCESSFUL; return NT_STATUS_OK; } -NTSTATUS gums_set_object_name(GUMS_OBJECT *obj, const char *name) +NTSTATUS gums_set_object_sid(GUMS_OBJECT *obj, const DOM_SID *sid) { - if (!obj || !name) + if (!obj || !sid) return NT_STATUS_INVALID_PARAMETER; - obj->name = (char *)talloc_strdup(obj->mem_ctx, name); - if (!(obj->name)) return NT_STATUS_UNSUCCESSFUL; + obj->sid = sid_dup_talloc(obj->mem_ctx, sid); + if (!(obj->sid)) return NT_STATUS_UNSUCCESSFUL; return NT_STATUS_OK; } -NTSTATUS gums_get_object_description(char **description, const GUMS_OBJECT *obj) +NTSTATUS gums_set_object_name(GUMS_OBJECT *obj, const char *name) { - if (!description || !obj) + if (!obj || !name) return NT_STATUS_INVALID_PARAMETER; - *description = obj->description; + obj->name = (char *)talloc_strdup(obj->mem_ctx, name); + if (!(obj->name)) return NT_STATUS_UNSUCCESSFUL; return NT_STATUS_OK; } @@ -353,8 +245,6 @@ NTSTATUS gums_set_object_description(GUMS_OBJECT *obj, const char *description) return NT_STATUS_OK; } -/* User specific functions */ - /* NTSTATUS gums_get_object_privileges(PRIVILEGE_SET **priv_set, const GUMS_OBJECT *obj) { @@ -366,16 +256,12 @@ NTSTATUS gums_get_object_privileges(PRIVILEGE_SET **priv_set, const GUMS_OBJECT } */ -NTSTATUS gums_get_domain_next_rid(uint32 *rid, const GUMS_OBJECT *obj) +uint32 gums_get_domain_next_rid(const GUMS_OBJECT *obj) { - if (!obj) - return NT_STATUS_INVALID_PARAMETER; - if (obj->type != GUMS_OBJ_DOMAIN) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return -1; - *rid = obj->data.domain->next_rid; - return NT_STATUS_OK; + return obj->data.domain->next_rid; } NTSTATUS gums_set_domain_next_rid(GUMS_OBJECT *obj, uint32 rid) @@ -390,340 +276,394 @@ NTSTATUS gums_set_domain_next_rid(GUMS_OBJECT *obj, uint32 rid) return NT_STATUS_OK; } -NTSTATUS gums_get_user_pri_group(DOM_SID **sid, const GUMS_OBJECT *obj) -{ - if (!sid || !obj) - return NT_STATUS_INVALID_PARAMETER; +/* User specific functions */ - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; +const DOM_SID *gums_get_user_pri_group(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - *sid = obj->data.user->group_sid; - return NT_STATUS_OK; + return obj->data.user->group_sid; } -NTSTATUS gums_set_user_pri_group(GUMS_OBJECT *obj, const DOM_SID *sid) +const DATA_BLOB gums_get_user_nt_pwd(const GUMS_OBJECT *obj) { - if (!obj || !sid) - return NT_STATUS_INVALID_PARAMETER; + fstring p; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return data_blob(NULL, 0); - obj->data.user->group_sid = sid_dup_talloc(obj->mem_ctx, sid); - if (!(obj->data.user->group_sid)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; + smbpasswd_sethexpwd(p, (unsigned char *)(obj->data.user->nt_pw.data), 0); + DEBUG(100, ("Reading NT Password=[%s]\n", p)); + + return obj->data.user->nt_pw; } -NTSTATUS gums_get_user_nt_pwd(DATA_BLOB **nt_pwd, const GUMS_OBJECT *obj) -{ - if (!nt_pwd || !obj) - return NT_STATUS_INVALID_PARAMETER; +const DATA_BLOB gums_get_user_lm_pwd(const GUMS_OBJECT *obj) +{ + fstring p; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return data_blob(NULL, 0); - *nt_pwd = &(obj->data.user->nt_pw); - return NT_STATUS_OK; + smbpasswd_sethexpwd(p, (unsigned char *)(obj->data.user->lm_pw.data), 0); + DEBUG(100, ("Reading LM Password=[%s]\n", p)); + + return obj->data.user->lm_pw; } -NTSTATUS gums_set_user_nt_pwd(GUMS_OBJECT *obj, const DATA_BLOB nt_pwd) +const char *gums_get_user_fullname(const GUMS_OBJECT *obj) { - if (!obj || nt_pwd.length != NT_HASH_LEN) - return NT_STATUS_INVALID_PARAMETER; - - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - obj->data.user->nt_pw = data_blob_talloc(obj->mem_ctx, nt_pwd.data, nt_pwd.length); - return NT_STATUS_OK; + return obj->data.user->full_name; } -NTSTATUS gums_get_user_lm_pwd(DATA_BLOB **lm_pwd, const GUMS_OBJECT *obj) -{ - if (!lm_pwd || !obj) - return NT_STATUS_INVALID_PARAMETER; - - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; +const char *gums_get_user_homedir(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - *lm_pwd = &(obj->data.user->lm_pw); - return NT_STATUS_OK; + return obj->data.user->home_dir; } -NTSTATUS gums_set_user_lm_pwd(GUMS_OBJECT *obj, const DATA_BLOB lm_pwd) +const char *gums_get_user_dir_drive(const GUMS_OBJECT *obj) { - if (!obj || lm_pwd.length != LM_HASH_LEN) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->dir_drive; +} - obj->data.user->lm_pw = data_blob_talloc(obj->mem_ctx, lm_pwd.data, lm_pwd.length); - return NT_STATUS_OK; +const char *gums_get_user_profile_path(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; + + return obj->data.user->profile_path; } -NTSTATUS gums_get_user_fullname(char **fullname, const GUMS_OBJECT *obj) +const char *gums_get_user_logon_script(const GUMS_OBJECT *obj) { - if (!fullname || !obj) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->logon_script; +} - *fullname = obj->data.user->full_name; - return NT_STATUS_OK; +const char *gums_get_user_workstations(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; + + return obj->data.user->workstations; } -NTSTATUS gums_set_user_fullname(GUMS_OBJECT *obj, const char *fullname) +const char *gums_get_user_unknown_str(const GUMS_OBJECT *obj) { - if (!obj || !fullname) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->unknown_str; +} - obj->data.user->full_name = (char *)talloc_strdup(obj->mem_ctx, fullname); - if (!(obj->data.user->full_name)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; +const char *gums_get_user_munged_dial(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; + + return obj->data.user->munged_dial; } -NTSTATUS gums_get_user_homedir(char **homedir, const GUMS_OBJECT *obj) +NTTIME gums_get_user_logon_time(const GUMS_OBJECT *obj) { - if (!homedir || !obj) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->logon_time; +} - *homedir = obj->data.user->home_dir; - return NT_STATUS_OK; +NTTIME gums_get_user_logoff_time(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } + + return obj->data.user->logoff_time; } -NTSTATUS gums_set_user_homedir(GUMS_OBJECT *obj, const char *homedir) +NTTIME gums_get_user_kickoff_time(const GUMS_OBJECT *obj) { - if (!obj || !homedir) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->kickoff_time; +} - obj->data.user->home_dir = (char *)talloc_strdup(obj->mem_ctx, homedir); - if (!(obj->data.user->home_dir)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; +NTTIME gums_get_user_pass_last_set_time(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } + + return obj->data.user->pass_last_set_time; } -NTSTATUS gums_get_user_dir_drive(char **dirdrive, const GUMS_OBJECT *obj) +NTTIME gums_get_user_pass_can_change_time(const GUMS_OBJECT *obj) { - if (!dirdrive || !obj) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->pass_can_change_time; +} - *dirdrive = obj->data.user->dir_drive; - return NT_STATUS_OK; +NTTIME gums_get_user_pass_must_change_time(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) { + NTTIME null_time; + init_nt_time(&null_time); + return null_time; + } + + return obj->data.user->pass_must_change_time; } -NTSTATUS gums_set_user_dir_drive(GUMS_OBJECT *obj, const char *dir_drive) +uint16 gums_get_user_acct_ctrl(const GUMS_OBJECT *obj) { - if (!obj || !dir_drive) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->acct_ctrl; +} - obj->data.user->dir_drive = (char *)talloc_strdup(obj->mem_ctx, dir_drive); - if (!(obj->data.user->dir_drive)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; +uint16 gums_get_user_logon_divs(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; + + return obj->data.user->logon_divs; } -NTSTATUS gums_get_user_logon_script(char **logon_script, const GUMS_OBJECT *obj) +uint32 gums_get_user_hours_len(const GUMS_OBJECT *obj) { - if (!logon_script || !obj) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->hours_len; +} - *logon_script = obj->data.user->logon_script; - return NT_STATUS_OK; +const uint8 *gums_get_user_hours(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return NULL; + + return obj->data.user->hours; } -NTSTATUS gums_set_user_logon_script(GUMS_OBJECT *obj, const char *logon_script) +uint32 gums_get_user_unknown_3(const GUMS_OBJECT *obj) { - if (!obj || !logon_script) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + return obj->data.user->unknown_3; +} - obj->data.user->logon_script = (char *)talloc_strdup(obj->mem_ctx, logon_script); - if (!(obj->data.user->logon_script)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; +uint16 gums_get_user_bad_password_count(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; + + return obj->data.user->bad_password_count; } -NTSTATUS gums_get_user_profile_path(char **profile_path, const GUMS_OBJECT *obj) +uint16 gums_get_user_logon_count(const GUMS_OBJECT *obj) { - if (!profile_path || !obj) - return NT_STATUS_INVALID_PARAMETER; - - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; - *profile_path = obj->data.user->profile_path; - return NT_STATUS_OK; + return obj->data.user->logon_count; } -NTSTATUS gums_set_user_profile_path(GUMS_OBJECT *obj, const char *profile_path) +uint32 gums_get_user_unknown_6(const GUMS_OBJECT *obj) { - if (!obj || !profile_path) - return NT_STATUS_INVALID_PARAMETER; + if (!obj || obj->type != GUMS_OBJ_NORMAL_USER) + return 0; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - obj->data.user->profile_path = (char *)talloc_strdup(obj->mem_ctx, profile_path); - if (!(obj->data.user->profile_path)) return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; + return obj->data.user->unknown_6; } -NTSTATUS gums_get_user_workstations(char **workstations, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_pri_group(GUMS_OBJECT *obj, const DOM_SID *sid) { - if (!workstations || !obj) + if (!obj || !sid) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *workstations = obj->data.user->workstations; + obj->data.user->group_sid = sid_dup_talloc(obj->mem_ctx, sid); + if (!(obj->data.user->group_sid)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_user_workstations(GUMS_OBJECT *obj, const char *workstations) +NTSTATUS gums_set_user_nt_pwd(GUMS_OBJECT *obj, const DATA_BLOB nt_pwd) { - if (!obj || !workstations) + fstring p; + unsigned char r[16]; + + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->workstations = (char *)talloc_strdup(obj->mem_ctx, workstations); - if (!(obj->data.user->workstations)) return NT_STATUS_NO_MEMORY; + obj->data.user->nt_pw = data_blob_talloc(obj->mem_ctx, nt_pwd.data, nt_pwd.length); + + memcpy(r, nt_pwd.data, 16); + smbpasswd_sethexpwd(p, r, 0); + DEBUG(100, ("Setting NT Password=[%s]\n", p)); + return NT_STATUS_OK; } -NTSTATUS gums_get_user_unknown_str(char **unknown_str, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_lm_pwd(GUMS_OBJECT *obj, const DATA_BLOB lm_pwd) { - if (!unknown_str || !obj) + fstring p; + unsigned char r[16]; + + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *unknown_str = obj->data.user->unknown_str; + obj->data.user->lm_pw = data_blob_talloc(obj->mem_ctx, lm_pwd.data, lm_pwd.length); + + memcpy(r, lm_pwd.data, 16); + smbpasswd_sethexpwd(p, r, 0); + DEBUG(100, ("Setting LM Password=[%s]\n", p)); + return NT_STATUS_OK; } -NTSTATUS gums_set_user_unknown_str(GUMS_OBJECT *obj, const char *unknown_str) +NTSTATUS gums_set_user_fullname(GUMS_OBJECT *obj, const char *fullname) { - if (!obj || !unknown_str) + if (!obj || !fullname) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->unknown_str = (char *)talloc_strdup(obj->mem_ctx, unknown_str); - if (!(obj->data.user->unknown_str)) return NT_STATUS_NO_MEMORY; + obj->data.user->full_name = (char *)talloc_strdup(obj->mem_ctx, fullname); + if (!(obj->data.user->full_name)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_get_user_munged_dial(char **munged_dial, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_homedir(GUMS_OBJECT *obj, const char *homedir) { - if (!munged_dial || !obj) + if (!obj || !homedir) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *munged_dial = obj->data.user->munged_dial; + obj->data.user->home_dir = (char *)talloc_strdup(obj->mem_ctx, homedir); + if (!(obj->data.user->home_dir)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_user_munged_dial(GUMS_OBJECT *obj, const char *munged_dial) +NTSTATUS gums_set_user_dir_drive(GUMS_OBJECT *obj, const char *dir_drive) { - if (!obj || !munged_dial) + if (!obj || !dir_drive) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->munged_dial = (char *)talloc_strdup(obj->mem_ctx, munged_dial); - if (!(obj->data.user->munged_dial)) return NT_STATUS_NO_MEMORY; + obj->data.user->dir_drive = (char *)talloc_strdup(obj->mem_ctx, dir_drive); + if (!(obj->data.user->dir_drive)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_get_user_logon_time(NTTIME *logon_time, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_logon_script(GUMS_OBJECT *obj, const char *logon_script) { - if (!logon_time || !obj) + if (!obj || !logon_script) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *logon_time = obj->data.user->logon_time; + obj->data.user->logon_script = (char *)talloc_strdup(obj->mem_ctx, logon_script); + if (!(obj->data.user->logon_script)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_user_logon_time(GUMS_OBJECT *obj, NTTIME logon_time) +NTSTATUS gums_set_user_profile_path(GUMS_OBJECT *obj, const char *profile_path) { - if (!obj) + if (!obj || !profile_path) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->logon_time = logon_time; + obj->data.user->profile_path = (char *)talloc_strdup(obj->mem_ctx, profile_path); + if (!(obj->data.user->profile_path)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_get_user_logoff_time(NTTIME *logoff_time, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_workstations(GUMS_OBJECT *obj, const char *workstations) { - if (!logoff_time || !obj) + if (!obj || !workstations) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *logoff_time = obj->data.user->logoff_time; + obj->data.user->workstations = (char *)talloc_strdup(obj->mem_ctx, workstations); + if (!(obj->data.user->workstations)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_user_logoff_time(GUMS_OBJECT *obj, NTTIME logoff_time) +NTSTATUS gums_set_user_unknown_str(GUMS_OBJECT *obj, const char *unknown_str) { - if (!obj) + if (!obj || !unknown_str) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->logoff_time = logoff_time; + obj->data.user->unknown_str = (char *)talloc_strdup(obj->mem_ctx, unknown_str); + if (!(obj->data.user->unknown_str)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_get_user_kickoff_time(NTTIME *kickoff_time, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_munged_dial(GUMS_OBJECT *obj, const char *munged_dial) { - if (!kickoff_time || !obj) + if (!obj || !munged_dial) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *kickoff_time = obj->data.user->kickoff_time; + obj->data.user->munged_dial = (char *)talloc_strdup(obj->mem_ctx, munged_dial); + if (!(obj->data.user->munged_dial)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_user_kickoff_time(GUMS_OBJECT *obj, NTTIME kickoff_time) +NTSTATUS gums_set_user_logon_time(GUMS_OBJECT *obj, NTTIME logon_time) { if (!obj) return NT_STATUS_INVALID_PARAMETER; @@ -731,23 +671,23 @@ NTSTATUS gums_set_user_kickoff_time(GUMS_OBJECT *obj, NTTIME kickoff_time) if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->kickoff_time = kickoff_time; + obj->data.user->logon_time = logon_time; return NT_STATUS_OK; } -NTSTATUS gums_get_user_pass_last_set_time(NTTIME *pass_last_set_time, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_logoff_time(GUMS_OBJECT *obj, NTTIME logoff_time) { - if (!pass_last_set_time || !obj) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *pass_last_set_time = obj->data.user->pass_last_set_time; + obj->data.user->logoff_time = logoff_time; return NT_STATUS_OK; } -NTSTATUS gums_set_user_pass_last_set_time(GUMS_OBJECT *obj, NTTIME pass_last_set_time) +NTSTATUS gums_set_user_kickoff_time(GUMS_OBJECT *obj, NTTIME kickoff_time) { if (!obj) return NT_STATUS_INVALID_PARAMETER; @@ -755,19 +695,19 @@ NTSTATUS gums_set_user_pass_last_set_time(GUMS_OBJECT *obj, NTTIME pass_last_set if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->pass_last_set_time = pass_last_set_time; + obj->data.user->kickoff_time = kickoff_time; return NT_STATUS_OK; } -NTSTATUS gums_get_user_pass_can_change_time(NTTIME *pass_can_change_time, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_pass_last_set_time(GUMS_OBJECT *obj, NTTIME pass_last_set_time) { - if (!pass_can_change_time || !obj) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *pass_can_change_time = obj->data.user->pass_can_change_time; + obj->data.user->pass_last_set_time = pass_last_set_time; return NT_STATUS_OK; } @@ -783,18 +723,6 @@ NTSTATUS gums_set_user_pass_can_change_time(GUMS_OBJECT *obj, NTTIME pass_can_ch return NT_STATUS_OK; } -NTSTATUS gums_get_user_pass_must_change_time(NTTIME *pass_must_change_time, const GUMS_OBJECT *obj) -{ - if (!pass_must_change_time || !obj) - return NT_STATUS_INVALID_PARAMETER; - - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - *pass_must_change_time = obj->data.user->pass_must_change_time; - return NT_STATUS_OK; -} - NTSTATUS gums_set_user_pass_must_change_time(GUMS_OBJECT *obj, NTTIME pass_must_change_time) { if (!obj) @@ -807,21 +735,21 @@ NTSTATUS gums_set_user_pass_must_change_time(GUMS_OBJECT *obj, NTTIME pass_must_ return NT_STATUS_OK; } -NTSTATUS gums_get_user_logon_divs(uint16 *logon_divs, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_acct_ctrl(GUMS_OBJECT *obj, uint16 acct_ctrl) { - if (!logon_divs || !obj) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *logon_divs = obj->data.user->logon_divs; + obj->data.user->acct_ctrl = acct_ctrl; return NT_STATUS_OK; } NTSTATUS gums_set_user_logon_divs(GUMS_OBJECT *obj, uint16 logon_divs) { - if (!obj || !logon_divs) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) @@ -831,19 +759,28 @@ NTSTATUS gums_set_user_logon_divs(GUMS_OBJECT *obj, uint16 logon_divs) return NT_STATUS_OK; } -NTSTATUS gums_get_user_hours_len(uint32 *hours_len, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_hours(GUMS_OBJECT *obj, uint32 hours_len, const uint8 *hours) { - if (!hours_len || !obj) + if (!obj || !hours) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *hours_len = obj->data.user->hours_len; + obj->data.user->hours_len = hours_len; + if (hours_len == 0) + DEBUG(10, ("gums_set_user_hours: Warning, hours_len is zero!\n")); + + obj->data.user->hours = (uint8 *)talloc(obj->mem_ctx, MAX_HOURS_LEN); + if (!(obj->data.user->hours)) + return NT_STATUS_NO_MEMORY; + if (hours_len) + memcpy(obj->data.user->hours, hours, hours_len); + return NT_STATUS_OK; } -NTSTATUS gums_set_user_hours_len(GUMS_OBJECT *obj, uint32 hours_len) +NTSTATUS gums_set_user_unknown_3(GUMS_OBJECT *obj, uint32 unknown_3) { if (!obj) return NT_STATUS_INVALID_PARAMETER; @@ -851,196 +788,206 @@ NTSTATUS gums_set_user_hours_len(GUMS_OBJECT *obj, uint32 hours_len) if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->hours_len = hours_len; + obj->data.user->unknown_3 = unknown_3; return NT_STATUS_OK; } -NTSTATUS gums_get_user_hours(uint8 **hours, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_bad_password_count(GUMS_OBJECT *obj, uint16 bad_password_count) { - if (!hours || !obj) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *hours = obj->data.user->hours; + obj->data.user->bad_password_count = bad_password_count; return NT_STATUS_OK; } -/* WARNING: always set hours_len before hours */ -NTSTATUS gums_set_user_hours(GUMS_OBJECT *obj, const uint8 *hours) +NTSTATUS gums_set_user_logon_count(GUMS_OBJECT *obj, uint16 logon_count) { - if (!obj || !hours) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - if (obj->data.user->hours_len == 0) - DEBUG(10, ("gums_set_user_hours: Warning, hours_len is zero!\n")); - - obj->data.user->hours = (uint8 *)talloc_memdup(obj->mem_ctx, hours, obj->data.user->hours_len); - if (!(obj->data.user->hours) & (obj->data.user->hours_len != 0)) return NT_STATUS_NO_MEMORY; + obj->data.user->logon_count = logon_count; return NT_STATUS_OK; } -NTSTATUS gums_get_user_unknown_3(uint32 *unknown_3, const GUMS_OBJECT *obj) +NTSTATUS gums_set_user_unknown_6(GUMS_OBJECT *obj, uint32 unknown_6) { - if (!unknown_3 || !obj) + if (!obj) return NT_STATUS_INVALID_PARAMETER; if (obj->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_OBJECT_TYPE_MISMATCH; - *unknown_3 = obj->data.user->unknown_3; + obj->data.user->unknown_6 = unknown_6; return NT_STATUS_OK; } -NTSTATUS gums_set_user_unknown_3(GUMS_OBJECT *obj, uint32 unknown_3) -{ - if (!obj) - return NT_STATUS_INVALID_PARAMETER; +/* Group specific functions */ - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; +const DOM_SID *gums_get_group_members(int *count, const GUMS_OBJECT *obj) +{ + if (!count || !obj || !(obj->type == GUMS_OBJ_GROUP || obj->type == GUMS_OBJ_ALIAS)) { + *count = -1; + return NULL; + } - obj->data.user->unknown_3 = unknown_3; - return NT_STATUS_OK; + *count = obj->data.group->count; + return obj->data.group->members; } -NTSTATUS gums_get_user_unknown_5(uint32 *unknown_5, const GUMS_OBJECT *obj) +NTSTATUS gums_set_group_members(GUMS_OBJECT *obj, uint32 count, DOM_SID *members) { - if (!unknown_5 || !obj) + uint32 n; + + if (!obj || ((count > 0) && !members)) return NT_STATUS_INVALID_PARAMETER; - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (obj->type != GUMS_OBJ_GROUP && + obj->type != GUMS_OBJ_ALIAS) + return NT_STATUS_OBJECT_TYPE_MISMATCH; - *unknown_5 = obj->data.user->unknown_5; - return NT_STATUS_OK; -} + obj->data.group->count = count; -NTSTATUS gums_set_user_unknown_5(GUMS_OBJECT *obj, uint32 unknown_5) -{ - if (!obj) - return NT_STATUS_INVALID_PARAMETER; + if (count) { + obj->data.group->members = (DOM_SID *)talloc(obj->mem_ctx, count * sizeof(DOM_SID)); + if (!(obj->data.group->members)) { + return NT_STATUS_NO_MEMORY; + } - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - obj->data.user->unknown_5 = unknown_5; + n = 0; + do { + sid_copy(&(obj->data.group->members[n]), &(members[n])); + n++; + } while (n < count); + } else { + obj->data.group->members = 0; + } + return NT_STATUS_OK; } -NTSTATUS gums_get_user_unknown_6(uint32 *unknown_6, const GUMS_OBJECT *obj) -{ - if (!unknown_6 || !obj) - return NT_STATUS_INVALID_PARAMETER; +/* Privilege specific functions */ - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; +const LUID_ATTR *gums_get_priv_luid_attr(const GUMS_OBJECT *obj) +{ + if (!obj || obj->type != GUMS_OBJ_PRIVILEGE) + return NULL; - *unknown_6 = obj->data.user->unknown_6; - return NT_STATUS_OK; + return obj->data.priv->privilege; } -NTSTATUS gums_set_user_unknown_6(GUMS_OBJECT *obj, uint32 unknown_6) +const DOM_SID *gums_get_priv_members(int *count, const GUMS_OBJECT *obj) { - if (!obj) - return NT_STATUS_INVALID_PARAMETER; - - if (obj->type != GUMS_OBJ_NORMAL_USER) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (!count || !obj || obj->type != GUMS_OBJ_PRIVILEGE) { + *count = -1; + return NULL; + } - obj->data.user->unknown_6 = unknown_6; - return NT_STATUS_OK; + *count = obj->data.priv->count; + return obj->data.priv->members; } -/* Group specific functions */ - -NTSTATUS gums_get_group_members(uint32 *count, DOM_SID **members, const GUMS_OBJECT *obj) +NTSTATUS gums_set_priv_luid_attr(GUMS_OBJECT *obj, LUID_ATTR *luid_attr) { - if (!count || !members || !obj) + if (!luid_attr || !obj) return NT_STATUS_INVALID_PARAMETER; - if (obj->type != GUMS_OBJ_GROUP && - obj->type != GUMS_OBJ_ALIAS) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (obj->type != GUMS_OBJ_PRIVILEGE) + return NT_STATUS_OBJECT_TYPE_MISMATCH; - *count = obj->data.group->count; - *members = *(obj->data.group->members); + obj->data.priv->privilege = (LUID_ATTR *)talloc_memdup(obj->mem_ctx, luid_attr, sizeof(LUID_ATTR)); + if (!(obj->data.priv->privilege)) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -NTSTATUS gums_set_group_members(GUMS_OBJECT *obj, uint32 count, DOM_SID **members) +NTSTATUS gums_set_priv_members(GUMS_OBJECT *obj, uint32 count, DOM_SID *members) { uint32 n; if (!obj || !members || !members) return NT_STATUS_INVALID_PARAMETER; - if (obj->type != GUMS_OBJ_GROUP && - obj->type != GUMS_OBJ_ALIAS) - return NT_STATUS_OBJECT_TYPE_MISMATCH; + if (obj->type != GUMS_OBJ_PRIVILEGE) + return NT_STATUS_OBJECT_TYPE_MISMATCH; + + obj->data.priv->count = count; + obj->data.priv->members = (DOM_SID *)talloc(obj->mem_ctx, count * sizeof(DOM_SID)); + if (!(obj->data.priv->members)) + return NT_STATUS_NO_MEMORY; - obj->data.group->count = count; n = 0; do { - obj->data.group->members[n] = sid_dup_talloc(obj->mem_ctx, members[n]); - if (!(obj->data.group->members[n])) return NT_STATUS_NO_MEMORY; + sid_copy(&(obj->data.priv->members[n]), &(members[n])); n++; } while (n < count); + return NT_STATUS_OK; } /* data_store set functions */ -NTSTATUS gums_create_commit_set(GUMS_COMMIT_SET **com_set, TALLOC_CTX *ctx, DOM_SID *sid, uint32 type) +NTSTATUS gums_create_commit_set(GUMS_COMMIT_SET **com_set, DOM_SID *sid, uint32 type) { TALLOC_CTX *mem_ctx; - GUMS_COMMIT_SET *set; mem_ctx = talloc_init("commit_set"); if (mem_ctx == NULL) return NT_STATUS_NO_MEMORY; - set = (GUMS_COMMIT_SET *)talloc(mem_ctx, sizeof(GUMS_COMMIT_SET)); - if (set == NULL) { + + *com_set = (GUMS_COMMIT_SET *)talloc_zero(mem_ctx, sizeof(GUMS_COMMIT_SET)); + if (*com_set == NULL) { talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } - set->mem_ctx = mem_ctx; - set->type = type; - sid_copy(&(set->sid), sid); - set->count = 0; - set->data = NULL; - *com_set = set; + (*com_set)->mem_ctx = mem_ctx; + (*com_set)->type = type; + sid_copy(&((*com_set)->sid), sid); return NT_STATUS_OK; } -NTSTATUS gums_cs_set_sec_desc(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, SEC_DESC *sec_desc) +NTSTATUS gums_cs_grow_data_set(GUMS_COMMIT_SET *com_set, int size) { GUMS_DATA_SET *data_set; - SEC_DESC *new_sec_desc; - if (!mem_ctx || !com_set || !sec_desc) - return NT_STATUS_INVALID_PARAMETER; - - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); + com_set->count = com_set->count + size; + if (com_set->count == size) { /* data set is empty*/ + data_set = (GUMS_DATA_SET *)talloc_zero(com_set->mem_ctx, sizeof(GUMS_DATA_SET)); } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); + data_set = (GUMS_DATA_SET *)talloc_realloc(com_set->mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); } if (data_set == NULL) return NT_STATUS_NO_MEMORY; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + com_set->data = data_set; + + return NT_STATUS_OK; +} + +NTSTATUS gums_cs_set_sec_desc(GUMS_COMMIT_SET *com_set, SEC_DESC *sec_desc) +{ + NTSTATUS ret; + GUMS_DATA_SET *data_set; + SEC_DESC *new_sec_desc; + + if (!com_set || !sec_desc) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; + + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = GUMS_SET_SEC_DESC; - new_sec_desc = dup_sec_desc(mem_ctx, sec_desc); + new_sec_desc = dup_sec_desc(com_set->mem_ctx, sec_desc); if (new_sec_desc == NULL) return NT_STATUS_NO_MEMORY; @@ -1050,87 +997,72 @@ NTSTATUS gums_cs_set_sec_desc(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, SEC } /* -NTSTATUS gums_cs_add_privilege(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, LUID_ATTR priv) +NTSTATUS gums_cs_add_privilege(GUMS_PRIV_COMMIT_SET *com_set, LUID_ATTR priv) { + NTSTATUS ret; GUMS_DATA_SET *data_set; LUID_ATTR *new_priv; - if (!mem_ctx || !com_set) + if (!com_set) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_OK(ret = gums_pcs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; data_set = ((com_set->data)[com_set->count - 1]); data_set->type = GUMS_ADD_PRIVILEGE; - if (NT_STATUS_IS_ERR(dupalloc_luid_attr(mem_ctx, &new_priv, priv))) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = dupalloc_luid_attr(com_set->mem_ctx, &new_priv, priv))) + return ret; (SEC_DESC *)(data_set->data) = new_priv; return NT_STATUS_OK; } -NTSTATUS gums_cs_del_privilege(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, LUID_ATTR priv) +NTSTATUS gums_cs_del_privilege(GUMS_PRIV_COMMIT_SET *com_set, LUID_ATTR priv) { + NTSTATUS ret; GUMS_DATA_SET *data_set; LUID_ATTR *new_priv; - if (!mem_ctx || !com_set) + if (!com_set) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_OK(ret = gums_pcs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; data_set = ((com_set->data)[com_set->count - 1]); data_set->type = GUMS_DEL_PRIVILEGE; - if (NT_STATUS_IS_ERR(dupalloc_luid_attr(mem_ctx, &new_priv, priv))) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = dupalloc_luid_attr(com_set->mem_ctx, &new_priv, priv))) + return ret; (SEC_DESC *)(data_set->data) = new_priv; return NT_STATUS_OK; } -NTSTATUS gums_cs_set_privilege_set(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, PRIVILEGE_SET *priv_set) +NTSTATUS gums_cs_set_privilege_set(GUMS_PRIV_COMMIT_SET *com_set, PRIVILEGE_SET *priv_set) { + NTSTATUS ret; GUMS_DATA_SET *data_set; PRIVILEGE_SET *new_priv_set; - if (!mem_ctx || !com_set || !priv_set) + if (!com_set || !priv_set) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_OK(ret = gums_pcs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; data_set = ((com_set->data)[com_set->count - 1]); data_set->type = GUMS_SET_PRIVILEGE; - if (NT_STATUS_IS_ERR(dup_priv_set(&new_priv_set, mem_ctx, priv_set))) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = init_priv_set_with_ctx(com_set->mem_ctx, &new_priv_set))) + return ret; + + if (!NT_STATUS_IS_OK(ret = dup_priv_set(new_priv_set, priv_set))) + return ret; (SEC_DESC *)(data_set->data) = new_priv_set; @@ -1138,28 +1070,22 @@ NTSTATUS gums_cs_set_privilege_set(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set } */ -NTSTATUS gums_cs_set_string(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, uint32 type, char *str) +NTSTATUS gums_cs_set_string(GUMS_COMMIT_SET *com_set, uint32 type, char *str) { + NTSTATUS ret; GUMS_DATA_SET *data_set; char *new_str; - if (!mem_ctx || !com_set || !str || type < GUMS_SET_NAME || type > GUMS_SET_MUNGED_DIAL) + if (!com_set || !str || type < GUMS_SET_NAME || type > GUMS_SET_MUNGED_DIAL) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = type; - new_str = talloc_strdup(mem_ctx, str); + new_str = talloc_strdup(com_set->mem_ctx, str); if (new_str == NULL) return NT_STATUS_NO_MEMORY; @@ -1168,102 +1094,96 @@ NTSTATUS gums_cs_set_string(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, uint3 return NT_STATUS_OK; } -NTSTATUS gums_cs_set_name(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *name) +NTSTATUS gums_cs_set_name(GUMS_COMMIT_SET *com_set, char *name) { - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, name); + return gums_cs_set_string(com_set, GUMS_SET_NAME, name); } -NTSTATUS gums_cs_set_description(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *desc) +NTSTATUS gums_cs_set_description(GUMS_COMMIT_SET *com_set, char *desc) { - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_DESCRIPTION, desc); + return gums_cs_set_string(com_set, GUMS_SET_DESCRIPTION, desc); } -NTSTATUS gums_cs_set_full_name(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *full_name) +NTSTATUS gums_cs_set_full_name(GUMS_COMMIT_SET *com_set, char *full_name) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, full_name); + return gums_cs_set_string(com_set, GUMS_SET_NAME, full_name); } -NTSTATUS gums_cs_set_home_directory(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *home_dir) +NTSTATUS gums_cs_set_home_directory(GUMS_COMMIT_SET *com_set, char *home_dir) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, home_dir); + return gums_cs_set_string(com_set, GUMS_SET_NAME, home_dir); } -NTSTATUS gums_cs_set_drive(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *drive) +NTSTATUS gums_cs_set_drive(GUMS_COMMIT_SET *com_set, char *drive) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, drive); + return gums_cs_set_string(com_set, GUMS_SET_NAME, drive); } -NTSTATUS gums_cs_set_logon_script(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *logon_script) +NTSTATUS gums_cs_set_logon_script(GUMS_COMMIT_SET *com_set, char *logon_script) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, logon_script); + return gums_cs_set_string(com_set, GUMS_SET_NAME, logon_script); } -NTSTATUS gums_cs_set_profile_path(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *prof_path) +NTSTATUS gums_cs_set_profile_path(GUMS_COMMIT_SET *com_set, char *prof_path) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, prof_path); + return gums_cs_set_string(com_set, GUMS_SET_NAME, prof_path); } -NTSTATUS gums_cs_set_workstations(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *wks) +NTSTATUS gums_cs_set_workstations(GUMS_COMMIT_SET *com_set, char *wks) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, wks); + return gums_cs_set_string(com_set, GUMS_SET_NAME, wks); } -NTSTATUS gums_cs_set_unknown_string(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *unkn_str) +NTSTATUS gums_cs_set_unknown_string(GUMS_COMMIT_SET *com_set, char *unkn_str) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, unkn_str); + return gums_cs_set_string(com_set, GUMS_SET_NAME, unkn_str); } -NTSTATUS gums_cs_set_munged_dial(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, char *munged_dial) +NTSTATUS gums_cs_set_munged_dial(GUMS_COMMIT_SET *com_set, char *munged_dial) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_string(mem_ctx, com_set, GUMS_SET_NAME, munged_dial); + return gums_cs_set_string(com_set, GUMS_SET_NAME, munged_dial); } -NTSTATUS gums_cs_set_nttime(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, uint32 type, NTTIME *nttime) +NTSTATUS gums_cs_set_nttime(GUMS_COMMIT_SET *com_set, uint32 type, NTTIME *nttime) { + NTSTATUS ret; GUMS_DATA_SET *data_set; NTTIME *new_time; - if (!mem_ctx || !com_set || !nttime || type < GUMS_SET_LOGON_TIME || type > GUMS_SET_PASS_MUST_CHANGE_TIME) + if (!com_set || !nttime || type < GUMS_SET_LOGON_TIME || type > GUMS_SET_PASS_MUST_CHANGE_TIME) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = type; - new_time = talloc(mem_ctx, sizeof(NTTIME)); + new_time = talloc(com_set->mem_ctx, sizeof(NTTIME)); if (new_time == NULL) return NT_STATUS_NO_MEMORY; @@ -1274,81 +1194,75 @@ NTSTATUS gums_cs_set_nttime(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, uint3 return NT_STATUS_OK; } -NTSTATUS gums_cs_set_logon_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *logon_time) +NTSTATUS gums_cs_set_logon_time(GUMS_COMMIT_SET *com_set, NTTIME *logon_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_LOGON_TIME, logon_time); + return gums_cs_set_nttime(com_set, GUMS_SET_LOGON_TIME, logon_time); } -NTSTATUS gums_cs_set_logoff_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *logoff_time) +NTSTATUS gums_cs_set_logoff_time(GUMS_COMMIT_SET *com_set, NTTIME *logoff_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_LOGOFF_TIME, logoff_time); + return gums_cs_set_nttime(com_set, GUMS_SET_LOGOFF_TIME, logoff_time); } -NTSTATUS gums_cs_set_kickoff_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *kickoff_time) +NTSTATUS gums_cs_set_kickoff_time(GUMS_COMMIT_SET *com_set, NTTIME *kickoff_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_KICKOFF_TIME, kickoff_time); + return gums_cs_set_nttime(com_set, GUMS_SET_KICKOFF_TIME, kickoff_time); } -NTSTATUS gums_cs_set_pass_last_set_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *pls_time) +NTSTATUS gums_cs_set_pass_last_set_time(GUMS_COMMIT_SET *com_set, NTTIME *pls_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_LOGON_TIME, pls_time); + return gums_cs_set_nttime(com_set, GUMS_SET_LOGON_TIME, pls_time); } -NTSTATUS gums_cs_set_pass_can_change_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *pcc_time) +NTSTATUS gums_cs_set_pass_can_change_time(GUMS_COMMIT_SET *com_set, NTTIME *pcc_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_LOGON_TIME, pcc_time); + return gums_cs_set_nttime(com_set, GUMS_SET_LOGON_TIME, pcc_time); } -NTSTATUS gums_cs_set_pass_must_change_time(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, NTTIME *pmc_time) +NTSTATUS gums_cs_set_pass_must_change_time(GUMS_COMMIT_SET *com_set, NTTIME *pmc_time) { if (com_set->type != GUMS_OBJ_NORMAL_USER) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_set_nttime(mem_ctx, com_set, GUMS_SET_LOGON_TIME, pmc_time); + return gums_cs_set_nttime(com_set, GUMS_SET_LOGON_TIME, pmc_time); } -NTSTATUS gums_cs_add_sids_to_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) +NTSTATUS gums_cs_add_sids_to_group(GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) { + NTSTATUS ret; GUMS_DATA_SET *data_set; DOM_SID **new_sids; int i; - if (!mem_ctx || !com_set || !sids) + if (!com_set || !sids) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = GUMS_ADD_SID_LIST; - new_sids = (DOM_SID **)talloc(mem_ctx, (sizeof(void *) * count)); + new_sids = (DOM_SID **)talloc(com_set->mem_ctx, (sizeof(void *) * count)); if (new_sids == NULL) return NT_STATUS_NO_MEMORY; for (i = 0; i < count; i++) { - new_sids[i] = sid_dup_talloc(mem_ctx, sids[i]); + new_sids[i] = sid_dup_talloc(com_set->mem_ctx, sids[i]); if (new_sids[i] == NULL) return NT_STATUS_NO_MEMORY; } @@ -1358,55 +1272,49 @@ NTSTATUS gums_cs_add_sids_to_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set return NT_STATUS_OK; } -NTSTATUS gums_cs_add_users_to_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) +NTSTATUS gums_cs_add_users_to_group(GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) { - if (!mem_ctx || !com_set || !sids) + if (!com_set || !sids) return NT_STATUS_INVALID_PARAMETER; if (com_set->type != GUMS_OBJ_GROUP || com_set->type != GUMS_OBJ_ALIAS) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_add_sids_to_group(mem_ctx, com_set, sids, count); + return gums_cs_add_sids_to_group(com_set, sids, count); } -NTSTATUS gums_cs_add_groups_to_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) +NTSTATUS gums_cs_add_groups_to_group(GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) { - if (!mem_ctx || !com_set || !sids) + if (!com_set || !sids) return NT_STATUS_INVALID_PARAMETER; if (com_set->type != GUMS_OBJ_ALIAS) return NT_STATUS_INVALID_PARAMETER; - return gums_cs_add_sids_to_group(mem_ctx, com_set, sids, count); + return gums_cs_add_sids_to_group(com_set, sids, count); } -NTSTATUS gums_cs_del_sids_from_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) +NTSTATUS gums_cs_del_sids_from_group(GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) { + NTSTATUS ret; GUMS_DATA_SET *data_set; DOM_SID **new_sids; int i; - if (!mem_ctx || !com_set || !sids) + if (!com_set || !sids) return NT_STATUS_INVALID_PARAMETER; if (com_set->type != GUMS_OBJ_GROUP || com_set->type != GUMS_OBJ_ALIAS) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = GUMS_DEL_SID_LIST; - new_sids = (DOM_SID **)talloc(mem_ctx, (sizeof(void *) * count)); + new_sids = (DOM_SID **)talloc(com_set->mem_ctx, (sizeof(void *) * count)); if (new_sids == NULL) return NT_STATUS_NO_MEMORY; for (i = 0; i < count; i++) { - new_sids[i] = sid_dup_talloc(mem_ctx, sids[i]); + new_sids[i] = sid_dup_talloc(com_set->mem_ctx, sids[i]); if (new_sids[i] == NULL) return NT_STATUS_NO_MEMORY; } @@ -1416,35 +1324,29 @@ NTSTATUS gums_cs_del_sids_from_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_s return NT_STATUS_OK; } -NTSTATUS gums_ds_set_sids_in_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) +NTSTATUS gums_ds_set_sids_in_group(GUMS_COMMIT_SET *com_set, const DOM_SID **sids, const uint32 count) { + NTSTATUS ret; GUMS_DATA_SET *data_set; DOM_SID **new_sids; int i; - if (!mem_ctx || !com_set || !sids) + if (!com_set || !sids) return NT_STATUS_INVALID_PARAMETER; if (com_set->type != GUMS_OBJ_GROUP || com_set->type != GUMS_OBJ_ALIAS) return NT_STATUS_INVALID_PARAMETER; - com_set->count = com_set->count + 1; - if (com_set->count == 1) { /* first data set */ - data_set = (GUMS_DATA_SET *)talloc(mem_ctx, sizeof(GUMS_DATA_SET)); - } else { - data_set = (GUMS_DATA_SET *)talloc_realloc(mem_ctx, com_set->data, sizeof(GUMS_DATA_SET) * com_set->count); - } - if (data_set == NULL) - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_cs_grow_data_set(com_set, 1))) + return ret; - com_set->data[0] = data_set; - data_set = ((com_set->data)[com_set->count - 1]); + data_set = &((com_set->data)[com_set->count - 1]); data_set->type = GUMS_SET_SID_LIST; - new_sids = (DOM_SID **)talloc(mem_ctx, (sizeof(void *) * count)); + new_sids = (DOM_SID **)talloc(com_set->mem_ctx, (sizeof(void *) * count)); if (new_sids == NULL) return NT_STATUS_NO_MEMORY; for (i = 0; i < count; i++) { - new_sids[i] = sid_dup_talloc(mem_ctx, sids[i]); + new_sids[i] = sid_dup_talloc(com_set->mem_ctx, sids[i]); if (new_sids[i] == NULL) return NT_STATUS_NO_MEMORY; } @@ -1454,10 +1356,16 @@ NTSTATUS gums_ds_set_sids_in_group(TALLOC_CTX *mem_ctx, GUMS_COMMIT_SET *com_set return NT_STATUS_OK; } - NTSTATUS gums_commit_data(GUMS_COMMIT_SET *set) { - return gums_storage->set_object_values(&(set->sid), set->count, set->data); + NTSTATUS ret; + GUMS_FUNCTIONS *fns; + + if (!NT_STATUS_IS_OK(ret = get_gums_fns(&fns))) { + DEBUG(0, ("gums_commit_data: unable to get gums functions! backend uninitialized?\n")); + return ret; + } + return fns->set_object_values(&(set->sid), set->count, set->data); } NTSTATUS gums_destroy_commit_set(GUMS_COMMIT_SET **com_set) diff --git a/source3/sam/gums_helper.c b/source3/sam/gums_helper.c index c22e6cf7ff..15486d094c 100644 --- a/source3/sam/gums_helper.c +++ b/source3/sam/gums_helper.c @@ -20,9 +20,8 @@ #include "includes.h" -extern GUMS_FUNCTIONS *gums_storage; - extern DOM_SID global_sid_World; +extern DOM_SID global_sid_Builtin; extern DOM_SID global_sid_Builtin_Administrators; extern DOM_SID global_sid_Builtin_Power_Users; extern DOM_SID global_sid_Builtin_Account_Operators; @@ -37,7 +36,7 @@ extern DOM_SID global_sid_Builtin_Guests; /* defines */ #define ALLOC_CHECK(str, ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) -#define NTSTATUS_CHECK(str1, str2, err, label) do { if (NT_STATUS_IS_ERR(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0) +#define NTSTATUS_CHECK(err, label, str1, str2) do { if (NT_STATUS_IS_ERR(err)) { DEBUG(0, ("%s: %s\n", str1, str2)); } } while(0) /**************************************************************************** Check if a user is a mapped group. @@ -75,224 +74,6 @@ NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid) } #endif -/**************************************************************************** - duplicate alloc luid_attr - ****************************************************************************/ -NTSTATUS dupalloc_luid_attr(TALLOC_CTX *ctx, LUID_ATTR **new_la, LUID_ATTR old_la) -{ - *new_la = (LUID_ATTR *)talloc(ctx, sizeof(LUID_ATTR)); - if (*new_la == NULL) { - DEBUG(0,("dupalloc_luid_attr: could not Alloc memory to duplicate LUID_ATTR\n")); - return NT_STATUS_NO_MEMORY; - } - - (*new_la)->luid.high = old_la.luid.high; - (*new_la)->luid.low = old_la.luid.low; - (*new_la)->attr = old_la.attr; - - return NT_STATUS_OK; -} - -/**************************************************************************** - initialise a privilege list - ****************************************************************************/ -void gums_init_privilege(PRIVILEGE_SET *priv_set) -{ - priv_set->count=0; - priv_set->control=0; - priv_set->set=NULL; -} - -/**************************************************************************** - add a privilege to a privilege array - ****************************************************************************/ -NTSTATUS gums_add_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx, LUID_ATTR set) -{ - LUID_ATTR *new_set; - - /* check if the privilege is not already in the list */ - if (gums_check_priv_in_privilege(priv_set, set)) - return NT_STATUS_UNSUCCESSFUL; - - /* we can allocate memory to add the new privilege */ - - new_set=(LUID_ATTR *)talloc_realloc(ctx, priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR))); - if (new_set==NULL) { - DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n")); - return NT_STATUS_NO_MEMORY; - } - - new_set[priv_set->count].luid.high=set.luid.high; - new_set[priv_set->count].luid.low=set.luid.low; - new_set[priv_set->count].attr=set.attr; - - priv_set->count++; - priv_set->set=new_set; - - return NT_STATUS_OK; -} - -/**************************************************************************** - add all the privileges to a privilege array - ****************************************************************************/ -NTSTATUS gums_add_all_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx) -{ - NTSTATUS result = NT_STATUS_OK; - LUID_ATTR set; - - set.attr=0; - set.luid.high=0; - - set.luid.low=SE_PRIV_ADD_USERS; - result = gums_add_privilege(priv_set, ctx, set); - NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done); - - set.luid.low=SE_PRIV_ADD_MACHINES; - result = gums_add_privilege(priv_set, ctx, set); - NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done); - - set.luid.low=SE_PRIV_PRINT_OPERATOR; - result = gums_add_privilege(priv_set, ctx, set); - NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done); - -done: - return result; -} - -/**************************************************************************** - check if the privilege list is empty - ****************************************************************************/ -BOOL gums_check_empty_privilege(PRIVILEGE_SET *priv_set) -{ - return (priv_set->count == 0); -} - -/**************************************************************************** - check if the privilege is in the privilege list - ****************************************************************************/ -BOOL gums_check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) -{ - int i; - - /* if the list is empty, obviously we can't have it */ - if (gums_check_empty_privilege(priv_set)) - return False; - - for (i=0; icount; i++) { - LUID_ATTR *cur_set; - - cur_set=&priv_set->set[i]; - /* check only the low and high part. Checking the attr field has no meaning */ - if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) ) - return True; - } - - return False; -} - -/**************************************************************************** - remove a privilege from a privilege array - ****************************************************************************/ -NTSTATUS gums_remove_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx, LUID_ATTR set) -{ - LUID_ATTR *new_set; - LUID_ATTR *old_set; - int i,j; - - /* check if the privilege is in the list */ - if (!gums_check_priv_in_privilege(priv_set, set)) - return NT_STATUS_UNSUCCESSFUL; - - /* special case if it's the only privilege in the list */ - if (priv_set->count==1) { - gums_init_privilege(priv_set); - return NT_STATUS_OK; - } - - /* - * the privilege is there, create a new list, - * and copy the other privileges - */ - - old_set = priv_set->set; - - new_set=(LUID_ATTR *)talloc(ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); - if (new_set==NULL) { - DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n")); - return NT_STATUS_NO_MEMORY; - } - - for (i=0, j=0; icount; i++) { - if ((old_set[i].luid.low == set.luid.low) && - (old_set[i].luid.high == set.luid.high)) { - continue; - } - - new_set[j].luid.low = old_set[i].luid.low; - new_set[j].luid.high = old_set[i].luid.high; - new_set[j].attr = old_set[i].attr; - - j++; - } - - if (j != priv_set->count - 1) { - DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); - DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); - return NT_STATUS_INTERNAL_ERROR; - } - - /* ok everything is fine */ - - priv_set->count--; - priv_set->set=new_set; - - return NT_STATUS_OK; -} - -/**************************************************************************** - duplicates a privilege array - ****************************************************************************/ -NTSTATUS gums_dup_priv_set(PRIVILEGE_SET **new_priv_set, TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set) -{ - LUID_ATTR *new_set; - LUID_ATTR *old_set; - int i; - - *new_priv_set = (PRIVILEGE_SET *)talloc(mem_ctx, sizeof(PRIVILEGE_SET)); - gums_init_privilege(*new_priv_set); - - /* special case if there are no privileges in the list */ - if (priv_set->count == 0) { - return NT_STATUS_OK; - } - - /* - * create a new list, - * and copy the other privileges - */ - - old_set = priv_set->set; - - new_set = (LUID_ATTR *)talloc(mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); - if (new_set==NULL) { - DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n")); - return NT_STATUS_NO_MEMORY; - } - - for (i=0; i < priv_set->count; i++) { - - new_set[i].luid.low = old_set[i].luid.low; - new_set[i].luid.high = old_set[i].luid.high; - new_set[i].attr = old_set[i].attr; - } - - (*new_priv_set)->count = priv_set->count; - (*new_priv_set)->control = priv_set->control; - (*new_priv_set)->set = new_set; - - return NT_STATUS_OK; -} - #define ALIAS_DEFAULT_SACL_SA_RIGHTS 0x01050013 #define ALIAS_DEFAULT_DACL_SA_RIGHTS \ (READ_CONTROL_ACCESS | \ @@ -302,7 +83,6 @@ NTSTATUS gums_dup_priv_set(PRIVILEGE_SET **new_priv_set, TALLOC_CTX *mem_ctx, PR #define ALIAS_DEFAULT_SACL_SEC_ACE_FLAG (SEC_ACE_FLAG_FAILED_ACCESS | SEC_ACE_FLAG_SUCCESSFUL_ACCESS) /* 0xc0 */ -#if 0 NTSTATUS create_builtin_alias_default_sec_desc(SEC_DESC **sec_desc, TALLOC_CTX *ctx) { DOM_SID *world = &global_sid_World; @@ -334,7 +114,7 @@ NTSTATUS create_builtin_alias_default_sec_desc(SEC_DESC **sec_desc, TALLOC_CTX * return NT_STATUS_NO_MEMORY; } - *sec_desc = make_sec_desc(ctx, SEC_DESC_REVISION, admins, admins, sacl, dacl, &psize); + *sec_desc = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, admins, admins, sacl, dacl, &psize); if (!(*sec_desc)) { DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n")); return NT_STATUS_NO_MEMORY; @@ -363,248 +143,243 @@ NTSTATUS sec_desc_add_ace_to_dacl(SEC_DESC *sec_desc, TALLOC_CTX *ctx, DOM_SID * return result; } -NTSTATUS gums_init_builtin_groups(void) +NTSTATUS gums_make_domain(DOM_SID *sid, const char *name, const char *description) { - NTSTATUS result; - GUMS_OBJECT g_obj; - GUMS_GROUP *g_grp; - GUMS_PRIVILEGE g_priv; - - /* Build the well known Builtin Local Groups */ - g_obj.type = GUMS_OBJ_GROUP; - g_obj.version = 1; - g_obj.seq_num = 0; - g_obj.mem_ctx = talloc_init("gums_init_backend_acct"); - if (g_obj.mem_ctx == NULL) { - DEBUG(0, ("gums_init_backend: Out of Memory!\n")); - return NT_STATUS_NO_MEMORY; - } + NTSTATUS ret; + GUMS_OBJECT *go; + GUMS_FUNCTIONS *fns; - /* Administrators * / + if (!NT_STATUS_IS_OK(ret = get_gums_fns(&fns))) + return ret; - /* alloc group structure */ - g_obj.data.group = (GUMS_GROUP *)talloc(g_obj.mem_ctx, sizeof(GUMS_GROUP)); - ALLOC_CHECK("gums_init_backend", g_obj.data.group, result, done); + if (!NT_STATUS_IS_OK(ret = gums_create_object(&go, GUMS_OBJ_DOMAIN))) + return ret; - /* make admins sid */ - g_grp = (GUMS_GROUP *)g_obj.data.group; - sid_copy(g_obj.sid, &global_sid_Builtin_Administrators); + ret = gums_set_object_sid(go, sid); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set sid!"); - /* make security descriptor */ - result = create_builtin_alias_default_sec_desc(&(g_obj.sec_desc), g_obj.mem_ctx); - NTSTATUS_CHECK("gums_init_backend", "create_builtin_alias_default_sec_desc", result, done); + ret = gums_set_object_name(go, name); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set name!"); - /* make privilege set */ - /* From BDC join trace: - SeSecurityPrivilege - SeBackupPrivilege - SeRestorePrivilege - SeSystemtimePrivilege - SeShutdownPrivilege - SeRemoteShutdownPrivilege - SeTakeOwnershipPrivilege - SeDebugPrivilege - SeSystemEnvironmentPrivilege - SeSystemProfilePrivilege - SeProfileSingleProcessPrivilege - SeIncreaseBasePriorityPrivilege - SeLocalDriverPrivilege - SeCreatePagefilePrivilege - SeIncreaseQuotaPrivilege - */ + if (description) { + ret = gums_set_object_description(go, description); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set description!"); + } - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Administrators"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); + /* make security descriptor * / + ret = create_builtin_alias_default_sec_desc(&((*go).sec_desc), (*go).mem_ctx); + NTSTATUS_CHECK(ret, error, "gums_init_backend", "create_builtin_alias_default_sec_desc"); + */ - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can fully administer the computer/domain"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); + ret = fns->set_object(go); - /* numebr of group members */ - g_grp->count = 0; - g_grp->members = NULL; +done: + gums_destroy_object(&go); + return ret; +} - /* store Administrators group */ - result = gums_storage->set_object(&g_obj); +NTSTATUS gums_make_alias(DOM_SID *sid, const char *name, const char *description) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + GUMS_FUNCTIONS *fns; - /* Power Users */ - /* Domain Controllers Does NOT have power Users */ + if (!NT_STATUS_IS_OK(ret = get_gums_fns(&fns))) + return ret; - sid_copy(g_obj.sid, &global_sid_Builtin_Power_Users); + if (!NT_STATUS_IS_OK(ret = gums_create_object(&go, GUMS_OBJ_ALIAS))) + return ret; - /* make privilege set */ - /* SE_PRIV_??? */ + ret = gums_set_object_sid(go, sid); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set sid!"); - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Power Users"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); + ret = gums_set_object_name(go, name); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set name!"); - /* set description */ -/* > */ g_obj.description = talloc_strdup(g_obj.mem_ctx, "Power Users"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); + if (description) { + ret = gums_set_object_description(go, description); + NTSTATUS_CHECK(ret, done, "gums_make_alias", "unable to set description!"); + } - /* store Power Users group */ - result = gums_storage->set_object(&g_obj); + /* make security descriptor * / + ret = create_builtin_alias_default_sec_desc(&((*go).sec_desc), (*go).mem_ctx); + NTSTATUS_CHECK(ret, error, "gums_init_backend", "create_builtin_alias_default_sec_desc"); + */ - /* Account Operators */ + ret = fns->set_object(go); - sid_copy(g_obj.sid, &global_sid_Builtin_Account_Operators); +done: + gums_destroy_object(&go); + return ret; +} - /* make privilege set */ - /* From BDC join trace: - SeShutdownPrivilege - */ +NTSTATUS gums_init_domain(DOM_SID *sid, const char *name) +{ + NTSTATUS ret; + + /* Add the weelknown Builtin Domain */ + if (!NT_STATUS_IS_OK(ret = gums_make_domain( + sid, + name, + NULL + ))) { + return ret; + } - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Account Operators"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); + /* Add default users and groups */ + /* Administrator + Guest + Domain Administrators + Domain Users + Domain Guests + */ - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain user and group accounts"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); + return ret; +} - /* store Account Operators group */ - result = gums_storage->set_object(&g_obj); +NTSTATUS gums_init_builtin_domain(void) +{ + NTSTATUS ret; - /* Server Operators */ + generate_wellknown_sids(); - sid_copy(g_obj.sid, &global_sid_Builtin_Server_Operators); + /* Add the weelknown Builtin Domain */ + if (!NT_STATUS_IS_OK(ret = gums_make_domain( + &global_sid_Builtin, + "BUILTIN", + "Builtin Domain" + ))) { + return ret; + } - /* make privilege set */ + /* Add the well known Builtin Local Groups */ + + /* Administrators */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Administrators, + "Administrators", + "Members can fully administer the computer/domain" + ))) { + return ret; + } + /* Administrator privilege set */ /* From BDC join trace: - SeBackupPrivilege - SeRestorePrivilege - SeSystemtimePrivilege - SeShutdownPrivilege - SeRemoteShutdownPrivilege + SeSecurityPrivilege, SeBackupPrivilege, SeRestorePrivilege, + SeSystemtimePrivilege, SeShutdownPrivilege, + SeRemoteShutdownPrivilege, SeTakeOwnershipPrivilege, + SeDebugPrivilege, SeSystemEnvironmentPrivilege, + SeSystemProfilePrivilege, SeProfileSingleProcessPrivilege, + SeIncreaseBasePriorityPrivilege, SeLocalDriverPrivilege, + SeCreatePagefilePrivilege, SeIncreaseQuotaPrivilege */ - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Server Operators"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain servers"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); - - /* store Server Operators group */ - result = gums_storage->set_object(&g_obj); + /* Power Users */ + /* Domain Controllers Does NOT have Power Users (?) */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Power_Users, + "Power Users", + "Power Users" + ))) { + return ret; + } - /* Print Operators */ + /* Power Users privilege set */ + /* (?) */ - sid_copy(g_obj.sid, &global_sid_Builtin_Print_Operators); + /* Account Operators */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Account_Operators, + "Account Operators", + "Members can administer domain user and group accounts" + ))) { + return ret; + } /* make privilege set */ /* From BDC join trace: SeShutdownPrivilege */ - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Print Operators"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain printers"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); - - /* store Print Operators group */ - result = gums_storage->set_object(&g_obj); + /* Server Operators */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Server_Operators, + "Server Operators", + "Members can administer domain servers" + ))) { + return ret; + } - /* Backup Operators */ + /* make privilege set */ + /* From BDC join trace: + SeBackupPrivilege, SeRestorePrivilege, SeSystemtimePrivilege, + SeShutdownPrivilege, SeRemoteShutdownPrivilege + */ - sid_copy(g_obj.sid, &global_sid_Builtin_Backup_Operators); + /* Print Operators */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Print_Operators, + "Print Operators", + "Members can administer domain printers" + ))) { + return ret; + } /* make privilege set */ /* From BDC join trace: - SeBackupPrivilege - SeRestorePrivilege SeShutdownPrivilege */ - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Backup Operators"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can bypass file security to backup files"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); + /* Backup Operators */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Backup_Operators, + "Backup Operators", + "Members can bypass file security to backup files" + ))) { + return ret; + } - /* store Backup Operators group */ - result = gums_storage->set_object(&g_obj); + /* make privilege set */ + /* From BDC join trace: + SeBackupPrivilege, SeRestorePrivilege, SeShutdownPrivilege + */ /* Replicator */ - - sid_copy(g_obj.sid, &global_sid_Builtin_Replicator); + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Replicator, + "Replicator", + "Supports file replication in a domain" + ))) { + return ret; + } /* make privilege set */ /* From BDC join trace: - SeBackupPrivilege - SeRestorePrivilege - SeShutdownPrivilege + SeBackupPrivilege, SeRestorePrivilege, SeShutdownPrivilege */ - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Replicator"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Supports file replication in a domain"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); - - /* store Replicator group */ - result = gums_storage->set_object(&g_obj); - /* Users */ + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Users, + "Users", + "Ordinary users" + ))) { + return ret; + } - sid_copy(g_obj.sid, &global_sid_Builtin_Users); - - /* add ACE to sec dsec dacl */ - sec_desc_add_ace_to_dacl(g_obj.sec_desc, g_obj.mem_ctx, &global_sid_Builtin_Account_Operators, ALIAS_DEFAULT_DACL_SA_RIGHTS); - sec_desc_add_ace_to_dacl(g_obj.sec_desc, g_obj.mem_ctx, &global_sid_Builtin_Power_Users, ALIAS_DEFAULT_DACL_SA_RIGHTS); - - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Users"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Ordinary users"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); - - /* store Users group */ - result = gums_storage->set_object(&g_obj); + /* Users specific ACEs * / + sec_desc_add_ace_to_dacl(go->sec_desc, go->mem_ctx, &global_sid_Builtin_Account_Operators, ALIAS_DEFAULT_DACL_SA_RIGHTS); + sec_desc_add_ace_to_dacl(go->sec_desc, go->mem_ctx, &global_sid_Builtin_Power_Users, ALIAS_DEFAULT_DACL_SA_RIGHTS); + */ /* Guests */ - - sid_copy(g_obj.sid, &global_sid_Builtin_Guests); - - /* set name */ - g_obj.name = talloc_strdup(g_obj.mem_ctx, "Guests"); - ALLOC_CHECK("gums_init_backend", g_obj.name, result, done); - - /* set description */ - g_obj.description = talloc_strdup(g_obj.mem_ctx, "Users granted guest access to the computer/domain"); - ALLOC_CHECK("gums_init_backend", g_obj.description, result, done); - - /* store Guests group */ - result = gums_storage->set_object(&g_obj); - - /* set default privileges */ - g_priv.type = GUMS_OBJ_GROUP; - g_priv.version = 1; - g_priv.seq_num = 0; - g_priv.mem_ctx = talloc_init("gums_init_backend_priv"); - if (g_priv.mem_ctx == NULL) { - DEBUG(0, ("gums_init_backend: Out of Memory!\n")); - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(ret = gums_make_alias( + &global_sid_Builtin_Guests, + "Guests", + "Users granted guest access to the computer/domain" + ))) { + return ret; } - - -done: - talloc_destroy(g_obj.mem_ctx); - talloc_destroy(g_priv.mem_ctx); - return result; + return ret; } -#endif -- cgit From ec82fb39f90d2a8b3b91259ae5e64cd1b28b3506 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Mon, 13 Oct 2003 23:14:46 +0000 Subject: Put back the changes that Simo reverted and fix a speling mistak. (This used to be commit 72b1f727754e2f9f54facba8615032c8118d928c) --- source3/nsswitch/wb_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 79553e9e4f..6c47d149f0 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -81,7 +81,7 @@ static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { return -1; } - /* Parinoia */ + /* Paranoia */ if (new_fd < 3) { close(new_fd); return -1; @@ -191,6 +191,8 @@ static int winbind_named_pipe_sock(const char *dir) if (connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { + DEBUG(10, ("error connecting to pipe socket: %s\n", + strerror(errno))); close(fd); return -1; } -- cgit From cd5245fbb9f800dae7c5f705d8f34f86ff7f2ff1 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 02:55:13 +0000 Subject: Ignore autogenerated tdbsam2_parse_info.h (This used to be commit bb2b8906a05109d5ba8ffff6c250d90d8658d444) --- source3/include/.cvsignore | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/include/.cvsignore b/source3/include/.cvsignore index 7dff121f14..6f72267aaa 100644 --- a/source3/include/.cvsignore +++ b/source3/include/.cvsignore @@ -1,7 +1,8 @@ build_env.h config.h -stamp-h -proto.h -wrepld_proto.h config.h.in +proto.h +stamp-h +tdbsam2_parse_info.h version.h +wrepld_proto.h -- cgit From 29eb1b4b4bd25fecd1eca8988b701adeb1f831e5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 03:13:21 +0000 Subject: Use @PICSUFFIX@ instead of .po in Makefile.in since we have gone to the trouble of detecting what the PIC suffix should actually be. Change PICFLAG in configure.in to PICFLAGS for consistency. Patches from Joachim Schmitz for bug 574. (This used to be commit 0abe1964f7de184d836b167dbc581454e6ec9df8) --- source3/Makefile.in | 144 +++++++++++++++++++++++++-------------------------- source3/configure.in | 51 ++++++++---------- 2 files changed, 95 insertions(+), 100 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 1d25058df6..e377c7a85e 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -453,7 +453,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o -PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/replace1.po lib/snprintf.po +PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.@PICSUFFIX@ nsswitch/wb_common.@PICSUFFIX@ lib/replace1.@PICSUFFIX@ lib/snprintf.@PICSUFFIX@ SMBW_OBJ1 = smbwrapper/smbw.o \ smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \ @@ -481,7 +481,7 @@ LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o -LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.po) +LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.@PICSUFFIX@) CLIENT_OBJ1 = client/client.o client/clitar.o @@ -585,17 +585,17 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \ $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) -WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.po) +WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.@PICSUFFIX@) -PICOBJS = $(SMBWRAPPER_OBJ:.o=.po) -LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.po) +PICOBJS = $(SMBWRAPPER_OBJ:.o=.@PICSUFFIX@) +LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@) PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \ lib/dummyroot.o $(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(SECRETS_OBJ) $(UBIQX_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ) -PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.po) +PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.@PICSUFFIX@) IDMAP_OBJ = sam/idmap.o sam/idmap_util.o @IDMAP_STATIC@ @@ -628,7 +628,7 @@ WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ WINBIND_NSS_OBJ = nsswitch/wb_common.o lib/replace1.o @WINBIND_NSS_EXTRA_OBJS@ -WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po) lib/snprintf.po +WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.@PICSUFFIX@) lib/snprintf.@PICSUFFIX@ POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o @@ -686,7 +686,7 @@ everything: all libsmbclient debug2html smbfilter talloctort modules torture \ $(EVERYTHING_PROGS) .SUFFIXES: -.SUFFIXES: .c .o .po .lo +.SUFFIXES: .c .o .@PICSUFFIX@ .lo SHOWFLAGS: @echo "Using FLAGS = $(FLAGS)" @@ -720,25 +720,25 @@ dynconfig.o: dynconfig.c Makefile @echo Compiling $*.c @$(CC) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ -dynconfig.po: dynconfig.c Makefile +dynconfig.@PICSUFFIX@: dynconfig.c Makefile @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi - @echo Compiling $*.c with @PICFLAG@ - @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAG@ -c $< -o $*.@PICSUFFIX@ -@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ -@POBAD_CC@ @mv $*.po.o $@ + @echo Compiling $*.c with @PICFLAGS@ + @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@ +@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@ +@POBAD_CC@ @mv $*.@PICSUFFIX@.o $@ lib/version.o: lib/version.c include/version.h @echo Compiling $*.c @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ -lib/version.po: lib/version.c include/version.h +lib/version.@PICSUFFIX@: lib/version.c include/version.h @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi - @echo Compiling $*.c with @PICFLAG@ - @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAG@ -c $< -o $*.@PICSUFFIX@ -@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ -@POBAD_CC@ @mv $*.po.o $@ + @echo Compiling $*.c with @PICFLAGS@ + @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@ +@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@ +@POBAD_CC@ @mv $*.@PICSUFFIX@.o $@ smbd/build_options.o: smbd/build_options.c Makefile include/config.h include/build_env.h include/proto.h @echo Compiling $*.c @@ -748,13 +748,13 @@ smbd/build_options.c: include/config.h.in script/mkbuildoptions.awk @echo Generating $@ @dir=smbd $(MAKEDIR) && $(AWK) -f $(srcdir)/script/mkbuildoptions.awk > $(builddir)/smbd/build_options.c < $(srcdir)/include/config.h.in -.c.po: +.c.@PICSUFFIX@: @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi - @echo Compiling $*.c with @PICFLAG@ - @$(CC) -I. -I$(srcdir) $(FLAGS) @PICFLAG@ -c $< -o $*.@PICSUFFIX@ -@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ -@POBAD_CC@ @mv $*.po.o $@ + @echo Compiling $*.c with @PICFLAGS@ + @$(CC) -I. -I$(srcdir) $(FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@ +@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@ +@POBAD_CC@ @mv $*.@PICSUFFIX@.o $@ bin/.dummy: @if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \ @@ -1026,112 +1026,112 @@ nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_PICOBJ) \ @SONAMEFLAG@`basename $@` -lpam -bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.po) +bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_RHOSTS_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/builtin.@SHLIBEXT@: $(AUTH_BUILTIN_OBJ:.o=.po) +bin/builtin.@SHLIBEXT@: $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_BUILTIN_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/domain.@SHLIBEXT@: $(AUTH_DOMAIN_OBJ:.o=.po) +bin/domain.@SHLIBEXT@: $(AUTH_DOMAIN_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_DOMAIN_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_DOMAIN_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/smbserver.@SHLIBEXT@: $(AUTH_SERVER_OBJ:.o=.po) +bin/smbserver.@SHLIBEXT@: $(AUTH_SERVER_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SERVER_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SERVER_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/winbind.@SHLIBEXT@: $(AUTH_WINBIND_OBJ:.o=.po) +bin/winbind.@SHLIBEXT@: $(AUTH_WINBIND_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_WINBIND_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_WINBIND_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/unix.@SHLIBEXT@: $(AUTH_UNIX_OBJ:.o=.po) +bin/unix.@SHLIBEXT@: $(AUTH_UNIX_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_UNIX_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_UNIX_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/sam.@SHLIBEXT@: $(AUTH_SAM_OBJ:.o=.po) +bin/sam.@SHLIBEXT@: $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SAM_OBJ:.o=.po) @SONAMEFLAG@`basename $@` + @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@` -bin/mysql.@SHLIBEXT@: $(MYSQL_OBJ:.o=.po) +bin/mysql.@SHLIBEXT@: $(MYSQL_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(MYSQL_OBJ:.o=.po) @MYSQL_LIBS@ \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(MYSQL_OBJ:.o=.@PICSUFFIX@) @MYSQL_LIBS@ \ @SONAMEFLAG@`basename $@` -bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.po +bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.@PICSUFFIX@ @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.po \ + @$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` -bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.po +bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.@PICSUFFIX@ @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_tdb.po \ + @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_tdb.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` -bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.po +bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.@PICSUFFIX@ @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.po \ + @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` -bin/weird.@SHLIBEXT@: $(DEVEL_HELP_WEIRD_OBJ:.o=.po) +bin/weird.@SHLIBEXT@: $(DEVEL_HELP_WEIRD_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/CP850.@SHLIBEXT@: $(DEVEL_HELP_CP850_OBJ:.o=.po) +bin/CP850.@SHLIBEXT@: $(DEVEL_HELP_CP850_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP850_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP850_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/CP437.@SHLIBEXT@: $(DEVEL_HELP_CP437_OBJ:.o=.po) +bin/CP437.@SHLIBEXT@: $(DEVEL_HELP_CP437_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP437_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP437_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/xml.@SHLIBEXT@: $(XML_OBJ:.o=.po) +bin/xml.@SHLIBEXT@: $(XML_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ:.o=.po) @XML_LIBS@ \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ:.o=.@PICSUFFIX@) @XML_LIBS@ \ @SONAMEFLAG@`basename $@` -bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.po) +bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ:.o=.po) +bin/extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXTD_AUDIT_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXTD_AUDIT_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ:.o=.po) +bin/recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ:.o=.po) +bin/netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ:.o=.po) +bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) +bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ:.o=.po) +bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` -bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.po) +bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @@ -1230,7 +1230,7 @@ PYTHON_OBJS = $(PARAM_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \ $(UBIQX_OBJ) $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o -PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.po) +PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.@PICSUFFIX@) python_ext: $(PYTHON_PICOBJS) @if test -z "$(PYTHON)"; then \ @@ -1295,10 +1295,10 @@ uninstallscripts: @$(SHELL) $(srcdir)/script/uninstallscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS) # Toplevel clean files -TOPFILES=dynconfig.o dynconfig.po +TOPFILES=dynconfig.o dynconfig.@PICSUFFIX@ clean: delheaders python_clean - -rm -f core */*~ *~ */*.o */*.po */*.@SHLIBEXT@ \ + -rm -f core */*~ *~ */*.o */*.@PICSUFFIX@ */*.@SHLIBEXT@ \ $(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(MODULES) $(TORTURE_PROGS) \ $(LIBSMBCLIENT) $(EVERYTHING_PROGS) .headers.stamp diff --git a/source3/configure.in b/source3/configure.in index 5c5cfb2ee2..a0dd6de2f9 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -141,7 +141,7 @@ AC_SUBST(LDSHFLAGS) AC_SUBST(SONAMEFLAG) AC_SUBST(SHLD) AC_SUBST(HOST_OS) -AC_SUBST(PICFLAG) +AC_SUBST(PICFLAGS) AC_SUBST(PICSUFFIX) AC_SUBST(POBAD_CC) AC_SUBST(SHLIBEXT) @@ -1031,7 +1031,7 @@ HOST_OS="$host_os" LDSHFLAGS="-shared" SONAMEFLAG="#" SHLD="\${CC} \${CFLAGS}" -PICFLAG="" +PICFLAGS="" PICSUFFIX="po" POBAD_CC="#" SHLIBEXT="so" @@ -1049,7 +1049,7 @@ if test "$enable_shared" = "yes"; then BLDSHARED="true" LDSHFLAGS="-shared" DYNEXP="-Wl,--export-dynamic" - PICFLAG="-fPIC" + PICFLAGS="-fPIC" SONAMEFLAG="-Wl,-soname=" AC_DEFINE(STAT_ST_BLOCKSIZE,512) ;; @@ -1058,12 +1058,12 @@ if test "$enable_shared" = "yes"; then LDSHFLAGS="-G" SONAMEFLAG="-h " if test "${GCC}" = "yes"; then - PICFLAG="-fPIC" + PICFLAGS="-fPIC" if test "${ac_cv_prog_gnu_ld}" = "yes"; then DYNEXP="-Wl,-E" fi else - PICFLAG="-KPIC" + PICFLAGS="-KPIC" ## ${CFLAGS} added for building 64-bit shared ## libs using Sun's Compiler LDSHFLAGS="-G \${CFLAGS}" @@ -1077,7 +1077,7 @@ if test "$enable_shared" = "yes"; then BLDSHARED="true" LDSHFLAGS="-G" SONAMEFLAG="-Wl,-h," - PICFLAG="-KPIC" # Is this correct for SunOS + PICFLAGS="-KPIC" # Is this correct for SunOS AC_DEFINE(STAT_ST_BLOCKSIZE,512) AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly]) ;; @@ -1085,7 +1085,7 @@ if test "$enable_shared" = "yes"; then LDSHFLAGS="-shared" DYNEXP="-Wl,--export-dynamic" SONAMEFLAG="-Wl,-soname," - PICFLAG="-fPIC -DPIC" + PICFLAGS="-fPIC -DPIC" AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block]) AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly]) ;; @@ -1093,7 +1093,7 @@ if test "$enable_shared" = "yes"; then LDSHFLAGS="-shared" DYNEXP="-Wl,-Bdynamic" SONAMEFLAG="-Wl,-soname," - PICFLAG="-fPIC" + PICFLAGS="-fPIC" AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block]) AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly]) ;; @@ -1107,9 +1107,9 @@ if test "$enable_shared" = "yes"; then SONAMEFLAG="-soname " SHLD="\${LD}" if test "${GCC}" = "yes"; then - PICFLAG="-fPIC" + PICFLAGS="-fPIC" else - PICFLAG="-KPIC" + PICFLAGS="-KPIC" fi AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block]) ;; @@ -1117,7 +1117,7 @@ if test "$enable_shared" = "yes"; then BLDSHARED="true" LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry,-berok" DYNEXP="-Wl,-brtl,-bexpall" - PICFLAG="-O2" + PICFLAGS="-O2" if test "${GCC}" != "yes"; then ## for funky AIX compiler using strncpy() CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000" @@ -1133,9 +1133,9 @@ if test "$enable_shared" = "yes"; then SHLD="/usr/bin/ld" LDSHFLAGS="-B symbolic -b -z" SONAMEFLAG="+h " - PICFLAG="+z" + PICFLAGS="+z" elif test "${GCC}" = "yes"; then - PICFLAG="-fPIC" + PICFLAGS="-fPIC" fi DYNEXP="-Wl,-E" AC_DEFINE(STAT_ST_BLOCKSIZE,8192,[The size of a block]) @@ -1148,7 +1148,7 @@ if test "$enable_shared" = "yes"; then BLDSHARED="true" LDSHFLAGS="-shared" SONAMEFLAG="-Wl,-soname," - PICFLAG="-fPIC" + PICFLAGS="-fPIC" AC_DEFINE(STAT_ST_BLOCKSIZE,512) AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly]) ;; @@ -1159,7 +1159,7 @@ if test "$enable_shared" = "yes"; then BLDSHARED="true" LDSHFLAGS="-shared" SONAMEFLAG="-Wl,-soname," - PICFLAG="-KPIC" + PICFLAGS="-KPIC" AC_DEFINE(STAT_ST_BLOCKSIZE,512) ;; *next2*) AC_DEFINE(NEXT2,1,[Whether the host os is NeXT v2]) @@ -1219,17 +1219,12 @@ AC_CACHE_CHECK([whether building shared libraries actually works], [ac_cv_shlib_works],[ ac_cv_shlib_works=no # try building a trivial shared library - if test "$PICSUFFIX" = "po"; then - $CC $CPPFLAGS $CFLAGS $PICFLAG -c -o shlib.po ${srcdir-.}/tests/shlib.c && - $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" shlib.po && - ac_cv_shlib_works=yes - else - $CC $CPPFLAGS $CFLAGS $PICFLAG -c -o shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c && - mv shlib.$PICSUFFIX shlib.po && - $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" shlib.po && - ac_cv_shlib_works=yes - fi - rm -f "shlib.$SHLIBEXT" shlib.po + $CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o \ + shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c && \ + $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \ + shlib.$PICSUFFIX && \ + ac_cv_shlib_works=yes + rm -f "shlib.$SHLIBEXT" shlib.$PICSUFFIX ]) if test $ac_cv_shlib_works = no; then BLDSHARED=false @@ -2185,7 +2180,7 @@ AC_ARG_WITH(smbwrapper, # Conditions under which smbwrapper should not be built. - if test x$PICFLAG = x; then + if test x$PICFLAGS = x; then echo No support for PIC code - disabling smbwrapper and smbsh WRAPPROG="" WRAP="" @@ -2798,7 +2793,7 @@ AC_ARG_WITH(pam_smbpass, # Conditions under which pam_smbpass should not be built. - if test x$PICFLAG = x; then + if test x$PICFLAGS = x; then AC_MSG_ERROR([No support for PIC code]) elif test x"$ac_cv_header_security_pam_appl_h" = x"no"; then AC_MSG_ERROR([No security/pam_appl.h found]) -- cgit From f631ec52abfca33fea5fe2b04c42e0ca68b17359 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 03:39:29 +0000 Subject: Set errno = ENOSYS if mmap not supported. From Joachim Schmitz (This used to be commit a94b91ee28fccba952e557f84886ff60251100b7) --- source3/utils/profiles.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c index 20b1222e72..a31674dfb2 100644 --- a/source3/utils/profiles.c +++ b/source3/utils/profiles.c @@ -614,6 +614,7 @@ int main(int argc, char *argv[]) base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); #else base = (char *)-1; + errno = ENOSYS; #endif if ((int)base == -1) { -- cgit From c06d6e0afe489fc13c0e5c5485fcf6f1298c52dc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 04:00:08 +0000 Subject: Enclose usage of st_blksize and st_blocks struct stat members in #ifdef HAVE_STAT_ST_BLKSIZE and #ifdef HAVE_STAT_ST_BLOCKS, respectively. Fixes bug 550 reported by Joachim Schmitz . (This used to be commit 3d777f5389ed6b4ab8c42eb110d41f7df309bead) --- source3/libsmb/libsmbclient.c | 4 ++++ source3/smbd/dosmode.c | 2 ++ source3/smbwrapper/smbw.c | 8 ++++++++ source3/smbwrapper/smbw_stat.c | 4 ++++ source3/torture/cmd_vfs.c | 12 ++++++++++++ 5 files changed, 30 insertions(+) (limited to 'source3') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 69c4d8f7a7..4eb7f49760 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -1139,8 +1139,12 @@ int smbc_setup_stat(SMBCCTX *context, struct stat *st, char *fname, size_t size, if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR; st->st_size = size; +#ifdef HAVE_STAT_ST_BLKSIZE st->st_blksize = 512; +#endif +#ifdef HAVE_STAT_ST_BLOCKS st->st_blocks = (size+511)/512; +#endif st->st_uid = getuid(); st->st_gid = getgid(); diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index aaee41b546..f88964123e 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -136,9 +136,11 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); +#if defined (HAVE_STAT_ST_BLOCKS) && defined (HAVE_STAT_ST_BLKSIZE) if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) { result |= FILE_ATTRIBUTE_SPARSE; } +#endif #ifdef S_ISLNK #if LINKS_READ_ONLY diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c index 7eb01c7da3..0ddacdf8ba 100644 --- a/source3/smbwrapper/smbw.c +++ b/source3/smbwrapper/smbw.c @@ -1480,8 +1480,12 @@ say no to acls st64->st_atime = st->st_atime; st64->st_mtime = st->st_mtime; st64->st_ctime = st->st_ctime; +#ifdef HAVE_STAT_ST_BLKSIZE st64->st_blksize = st->st_blksize; +#endif +#ifdef HAVE_STAT_ST_BLOCKS st64->st_blocks = st->st_blocks; +#endif } #endif @@ -1545,8 +1549,12 @@ struct kernel_stat { st->st_gid = kbuf->st_gid; st->st_rdev = kbuf->st_rdev; st->st_size = kbuf->st_size; +#ifdef HAVE_STAT_ST_BLKSIZE st->st_blksize = kbuf->st_blksize; +#endif +#ifdef HAVE_STAT_ST_BLOCKS st->st_blocks = kbuf->st_blocks; +#endif st->st_atime = kbuf->st_atime_; st->st_mtime = kbuf->st_mtime_; st->st_ctime = kbuf->st_ctime_; diff --git a/source3/smbwrapper/smbw_stat.c b/source3/smbwrapper/smbw_stat.c index 6c476a8a67..bb76ef006a 100644 --- a/source3/smbwrapper/smbw_stat.c +++ b/source3/smbwrapper/smbw_stat.c @@ -41,8 +41,12 @@ void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode) if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR; st->st_size = size; +#ifdef HAVE_STAT_ST_BLKSIZE st->st_blksize = 512; +#endif +#ifdef HAVE_STAT_ST_BLOCKS st->st_blocks = (size+511)/512; +#endif st->st_uid = getuid(); st->st_gid = getgid(); if (IS_DOS_DIR(mode)) { diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 8317a57a20..bfce4b88b4 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -522,8 +522,12 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); printf(" Size: %10u", (unsigned int)st.st_size); +#ifdef HAVE_STAT_ST_BLOCKS printf(" Blocks: %9u", (unsigned int)st.st_blocks); +#endif +#ifdef HAVE_STAT_ST_BLKSIZE printf(" IO Block: %u\n", (unsigned int)st.st_blksize); +#endif printf(" Device: 0x%10x", (unsigned int)st.st_dev); printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); @@ -586,8 +590,12 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); printf(" Size: %10u", (unsigned int)st.st_size); +#ifdef HAVE_STAT_ST_BLOCKS printf(" Blocks: %9u", (unsigned int)st.st_blocks); +#endif +#ifdef HAVE_STAT_ST_BLKSIZE printf(" IO Block: %u\n", (unsigned int)st.st_blksize); +#endif printf(" Device: 0x%10x", (unsigned int)st.st_dev); printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); @@ -638,8 +646,12 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); printf(" Size: %10u", (unsigned int)st.st_size); +#ifdef HAVE_STAT_ST_BLOCKS printf(" Blocks: %9u", (unsigned int)st.st_blocks); +#endif +#ifdef HAVE_STAT_ST_BLKSIZE printf(" IO Block: %u\n", (unsigned int)st.st_blksize); +#endif printf(" Device: 0x%10x", (unsigned int)st.st_dev); printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); -- cgit From d6e17a943c4e19c610e43f844e91152e5708a01b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 04:00:39 +0000 Subject: Delete unused label to fix compiler warning. (This used to be commit e982dd5bc4c7c0215bd4f2daf13da506c00b7cb9) --- source3/lib/privileges.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index 1c23d9e40e..1ed583382d 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -188,7 +188,6 @@ NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set) result = add_privilege(priv_set, set); NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); -done: return result; } -- cgit From 4162ac5972cd5735e4184fdf7f4142801b7eb54c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Oct 2003 07:43:41 +0000 Subject: sorry folks, forgot to cvs add/remove before commit. (This used to be commit 0ed85e6a2dff0953dbbd5ff4723ef6941ec32850) --- source3/include/tdbsam2_parse_info.h | 164 +++++ source3/passdb/pdb_gums.c | 462 ++++++++++++ source3/sam/gumm_tdb.c | 1196 ------------------------------- source3/sam/gums_tdbsam2.c | 1297 ++++++++++++++++++++++++++++++++++ 4 files changed, 1923 insertions(+), 1196 deletions(-) create mode 100644 source3/include/tdbsam2_parse_info.h create mode 100644 source3/passdb/pdb_gums.c delete mode 100644 source3/sam/gumm_tdb.c create mode 100644 source3/sam/gums_tdbsam2.c (limited to 'source3') diff --git a/source3/include/tdbsam2_parse_info.h b/source3/include/tdbsam2_parse_info.h new file mode 100644 index 0000000000..f1b2936c47 --- /dev/null +++ b/source3/include/tdbsam2_parse_info.h @@ -0,0 +1,164 @@ +/* This is an automatically generated file - DO NOT EDIT! */ + +int gen_dump_struct_domain_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_domain_sub_structure(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_domain_sub_structure[] = { +{"next_rid", 0, sizeof(uint32), offsetof(struct domain_sub_structure, next_rid), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_domain_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_domain_sub_structure, p, ptr, indent); +} +int gen_parse_struct_domain_sub_structure(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_domain_sub_structure, ptr, str); +} + +int gen_dump_struct_tdbsam2_domain_data(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_tdbsam2_domain_data(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_tdbsam2_domain_data[] = { +{"mem_ctx", 1, sizeof(TALLOC_CTX), offsetof(struct tdbsam2_domain_data, mem_ctx), 0, NULL, 0, gen_dump_TALLOC_CTX, gen_parse_TALLOC_CTX}, +{"type", 0, sizeof(uint32), offsetof(struct tdbsam2_domain_data, type), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"version", 0, sizeof(uint32), offsetof(struct tdbsam2_domain_data, version), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"xcounter", 0, sizeof(uint32), offsetof(struct tdbsam2_domain_data, xcounter), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"sec_desc", 1, sizeof(SEC_DESC), offsetof(struct tdbsam2_domain_data, sec_desc), 0, NULL, 0, gen_dump_SEC_DESC, gen_parse_SEC_DESC}, +{"dom_sid", 1, sizeof(DOM_SID), offsetof(struct tdbsam2_domain_data, dom_sid), 0, NULL, 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{"name", 1, sizeof(char), offsetof(struct tdbsam2_domain_data, name), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"description", 1, sizeof(char), offsetof(struct tdbsam2_domain_data, description), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"dss", 1, sizeof(struct domain_sub_structure), offsetof(struct tdbsam2_domain_data, dss), 0, NULL, 0, gen_dump_struct_domain_sub_structure, gen_parse_struct_domain_sub_structure}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_tdbsam2_domain_data(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_tdbsam2_domain_data, p, ptr, indent); +} +int gen_parse_struct_tdbsam2_domain_data(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_tdbsam2_domain_data, ptr, str); +} + +int gen_dump_struct_user_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_user_sub_structure(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_user_sub_structure[] = { +{"group_sid", 1, sizeof(DOM_SID), offsetof(struct user_sub_structure, group_sid), 0, NULL, 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{"logon_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, logon_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"logoff_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, logoff_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"kickoff_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, kickoff_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"pass_last_set_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, pass_last_set_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"pass_can_change_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, pass_can_change_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"pass_must_change_time", 0, sizeof(NTTIME), offsetof(struct user_sub_structure, pass_must_change_time), 0, NULL, 0, gen_dump_NTTIME, gen_parse_NTTIME}, +{"full_name", 1, sizeof(char), offsetof(struct user_sub_structure, full_name), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"home_dir", 1, sizeof(char), offsetof(struct user_sub_structure, home_dir), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"dir_drive", 1, sizeof(char), offsetof(struct user_sub_structure, dir_drive), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"logon_script", 1, sizeof(char), offsetof(struct user_sub_structure, logon_script), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"profile_path", 1, sizeof(char), offsetof(struct user_sub_structure, profile_path), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"workstations", 1, sizeof(char), offsetof(struct user_sub_structure, workstations), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"unknown_str", 1, sizeof(char), offsetof(struct user_sub_structure, unknown_str), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"munged_dial", 1, sizeof(char), offsetof(struct user_sub_structure, munged_dial), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"lm_pw", 0, sizeof(DATA_BLOB), offsetof(struct user_sub_structure, lm_pw), 0, NULL, 0, gen_dump_DATA_BLOB, gen_parse_DATA_BLOB}, +{"nt_pw", 0, sizeof(DATA_BLOB), offsetof(struct user_sub_structure, nt_pw), 0, NULL, 0, gen_dump_DATA_BLOB, gen_parse_DATA_BLOB}, +{"acct_ctrl", 0, sizeof(uint16), offsetof(struct user_sub_structure, acct_ctrl), 0, NULL, 0, gen_dump_uint16, gen_parse_uint16}, +{"logon_divs", 0, sizeof(uint16), offsetof(struct user_sub_structure, logon_divs), 0, NULL, 0, gen_dump_uint16, gen_parse_uint16}, +{"hours_len", 0, sizeof(uint32), offsetof(struct user_sub_structure, hours_len), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"hours", 1, sizeof(uint8), offsetof(struct user_sub_structure, hours), 0, "hours_len", 0, gen_dump_uint8, gen_parse_uint8}, +{"bad_password_count", 0, sizeof(uint16), offsetof(struct user_sub_structure, bad_password_count), 0, NULL, 0, gen_dump_uint16, gen_parse_uint16}, +{"logon_count", 0, sizeof(uint16), offsetof(struct user_sub_structure, logon_count), 0, NULL, 0, gen_dump_uint16, gen_parse_uint16}, +{"unknown_3", 0, sizeof(uint32), offsetof(struct user_sub_structure, unknown_3), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"unknown_6", 0, sizeof(uint32), offsetof(struct user_sub_structure, unknown_6), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_user_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_user_sub_structure, p, ptr, indent); +} +int gen_parse_struct_user_sub_structure(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_user_sub_structure, ptr, str); +} + +int gen_dump_struct_tdbsam2_user_data(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_tdbsam2_user_data(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_tdbsam2_user_data[] = { +{"mem_ctx", 1, sizeof(TALLOC_CTX), offsetof(struct tdbsam2_user_data, mem_ctx), 0, NULL, 0, gen_dump_TALLOC_CTX, gen_parse_TALLOC_CTX}, +{"type", 0, sizeof(uint32), offsetof(struct tdbsam2_user_data, type), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"version", 0, sizeof(uint32), offsetof(struct tdbsam2_user_data, version), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"xcounter", 0, sizeof(uint32), offsetof(struct tdbsam2_user_data, xcounter), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"sec_desc", 1, sizeof(SEC_DESC), offsetof(struct tdbsam2_user_data, sec_desc), 0, NULL, 0, gen_dump_SEC_DESC, gen_parse_SEC_DESC}, +{"user_sid", 1, sizeof(DOM_SID), offsetof(struct tdbsam2_user_data, user_sid), 0, NULL, 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{"name", 1, sizeof(char), offsetof(struct tdbsam2_user_data, name), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"description", 1, sizeof(char), offsetof(struct tdbsam2_user_data, description), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"uss", 1, sizeof(struct user_sub_structure), offsetof(struct tdbsam2_user_data, uss), 0, NULL, 0, gen_dump_struct_user_sub_structure, gen_parse_struct_user_sub_structure}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_tdbsam2_user_data(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_tdbsam2_user_data, p, ptr, indent); +} +int gen_parse_struct_tdbsam2_user_data(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_tdbsam2_user_data, ptr, str); +} + +int gen_dump_struct_group_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_group_sub_structure(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_group_sub_structure[] = { +{"count", 0, sizeof(uint32), offsetof(struct group_sub_structure, count), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"members", 1, sizeof(DOM_SID), offsetof(struct group_sub_structure, members), 0, "count", 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_group_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_group_sub_structure, p, ptr, indent); +} +int gen_parse_struct_group_sub_structure(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_group_sub_structure, ptr, str); +} + +int gen_dump_struct_tdbsam2_group_data(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_tdbsam2_group_data(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_tdbsam2_group_data[] = { +{"mem_ctx", 1, sizeof(TALLOC_CTX), offsetof(struct tdbsam2_group_data, mem_ctx), 0, NULL, 0, gen_dump_TALLOC_CTX, gen_parse_TALLOC_CTX}, +{"type", 0, sizeof(uint32), offsetof(struct tdbsam2_group_data, type), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"version", 0, sizeof(uint32), offsetof(struct tdbsam2_group_data, version), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"xcounter", 0, sizeof(uint32), offsetof(struct tdbsam2_group_data, xcounter), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"sec_desc", 1, sizeof(SEC_DESC), offsetof(struct tdbsam2_group_data, sec_desc), 0, NULL, 0, gen_dump_SEC_DESC, gen_parse_SEC_DESC}, +{"group_sid", 1, sizeof(DOM_SID), offsetof(struct tdbsam2_group_data, group_sid), 0, NULL, 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{"name", 1, sizeof(char), offsetof(struct tdbsam2_group_data, name), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"description", 1, sizeof(char), offsetof(struct tdbsam2_group_data, description), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"gss", 1, sizeof(struct group_sub_structure), offsetof(struct tdbsam2_group_data, gss), 0, NULL, 0, gen_dump_struct_group_sub_structure, gen_parse_struct_group_sub_structure}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_tdbsam2_group_data(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_tdbsam2_group_data, p, ptr, indent); +} +int gen_parse_struct_tdbsam2_group_data(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_tdbsam2_group_data, ptr, str); +} + +int gen_dump_struct_priv_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_priv_sub_structure(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_priv_sub_structure[] = { +{"privilege", 1, sizeof(LUID_ATTR), offsetof(struct priv_sub_structure, privilege), 0, NULL, 0, gen_dump_LUID_ATTR, gen_parse_LUID_ATTR}, +{"count", 0, sizeof(uint32), offsetof(struct priv_sub_structure, count), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"members", 1, sizeof(DOM_SID), offsetof(struct priv_sub_structure, members), 0, "count", 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_priv_sub_structure(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_priv_sub_structure, p, ptr, indent); +} +int gen_parse_struct_priv_sub_structure(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_priv_sub_structure, ptr, str); +} + +int gen_dump_struct_tdbsam2_priv_data(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned); +int gen_parse_struct_tdbsam2_priv_data(TALLOC_CTX *mem_ctx, char *, const char *); +static const struct parse_struct pinfo_tdbsam2_priv_data[] = { +{"mem_ctx", 1, sizeof(TALLOC_CTX), offsetof(struct tdbsam2_priv_data, mem_ctx), 0, NULL, 0, gen_dump_TALLOC_CTX, gen_parse_TALLOC_CTX}, +{"type", 0, sizeof(uint32), offsetof(struct tdbsam2_priv_data, type), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"version", 0, sizeof(uint32), offsetof(struct tdbsam2_priv_data, version), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"xcounter", 0, sizeof(uint32), offsetof(struct tdbsam2_priv_data, xcounter), 0, NULL, 0, gen_dump_uint32, gen_parse_uint32}, +{"null_sid", 1, sizeof(DOM_SID), offsetof(struct tdbsam2_priv_data, null_sid), 0, NULL, 0, gen_dump_DOM_SID, gen_parse_DOM_SID}, +{"name", 1, sizeof(char), offsetof(struct tdbsam2_priv_data, name), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"description", 1, sizeof(char), offsetof(struct tdbsam2_priv_data, description), 0, NULL, FLAG_NULLTERM, gen_dump_char, gen_parse_char}, +{"pss", 1, sizeof(struct priv_sub_structure), offsetof(struct tdbsam2_priv_data, pss), 0, NULL, 0, gen_dump_struct_priv_sub_structure, gen_parse_struct_priv_sub_structure}, +{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}}; + +int gen_dump_struct_tdbsam2_priv_data(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(mem_ctx, pinfo_tdbsam2_priv_data, p, ptr, indent); +} +int gen_parse_struct_tdbsam2_priv_data(TALLOC_CTX *mem_ctx, char *ptr, const char *str) { + return gen_parse_struct(mem_ctx, pinfo_tdbsam2_priv_data, ptr, str); +} + diff --git a/source3/passdb/pdb_gums.c b/source3/passdb/pdb_gums.c new file mode 100644 index 0000000000..dd6e682452 --- /dev/null +++ b/source3/passdb/pdb_gums.c @@ -0,0 +1,462 @@ +/* + * 'Guest' password backend for samba + * Copyright (C) Jelmer Vernooij 2002 + * Copyright (C) Andrew Bartlett 2003 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#define SET_OR_FAIL(func, label) do { if (!NT_STATUS_IS_OK(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0) +#define BOOL_SET_OR_FAIL(func, label) do { if (!func) { DEBUG(0, ("%s: Setting sam object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0) + +struct gums_gw_data { + GUMS_FUNCTIONS *fns; + void *handle; +}; + +static NTSTATUS gums_object_to_sam_account(SAM_ACCOUNT *sa, GUMS_OBJECT *go) +{ + NTSTATUS ret; + NTTIME nt_time; + DATA_BLOB pwd; + + if (!go || !sa) + return NT_STATUS_INVALID_PARAMETER; +/* + if (!NT_STATUS_IS_OK(ret = pdb_init_sam(sa))) { + DEBUG(0, ("gums_object_to_sam_account: error occurred while creating sam_account object!\n")); + goto error; + } +*/ + if (gums_get_object_type(go) != GUMS_OBJ_NORMAL_USER) + return NT_STATUS_OBJECT_TYPE_MISMATCH; + + BOOL_SET_OR_FAIL(pdb_set_acct_ctrl(sa, gums_get_user_acct_ctrl(go), PDB_SET), error); + + /* domain */ + /* unix_homedir ? */ + + nt_time = gums_get_user_logon_time(go); + BOOL_SET_OR_FAIL(pdb_set_logon_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + nt_time = gums_get_user_logoff_time(go); + BOOL_SET_OR_FAIL(pdb_set_logoff_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + nt_time = gums_get_user_kickoff_time(go); + BOOL_SET_OR_FAIL(pdb_set_kickoff_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + nt_time = gums_get_user_pass_last_set_time(go); + BOOL_SET_OR_FAIL(pdb_set_pass_last_set_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + nt_time = gums_get_user_pass_can_change_time(go); + BOOL_SET_OR_FAIL(pdb_set_pass_can_change_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + nt_time = gums_get_user_pass_must_change_time(go); + BOOL_SET_OR_FAIL(pdb_set_pass_must_change_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_hours_len(sa, gums_get_user_hours_len(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_logon_divs(sa, gums_get_user_logon_divs(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_user_sid(sa, gums_get_object_sid(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_group_sid(sa, gums_get_user_pri_group(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_username(sa, gums_get_object_name(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_nt_username(sa, gums_get_object_name(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_fullname(sa, gums_get_user_fullname(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_logon_script(sa, gums_get_user_logon_script(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_profile_path(sa, gums_get_user_profile_path(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_dir_drive(sa, gums_get_user_dir_drive(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_homedir(sa, gums_get_user_homedir(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_acct_desc(sa, gums_get_object_description(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_workstations(sa, gums_get_user_workstations(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_unknown_str(sa, gums_get_user_unknown_str(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_munged_dial(sa, gums_get_user_munged_dial(go), PDB_SET), error); + + pwd = gums_get_user_nt_pwd(go); + if (!pdb_set_nt_passwd(sa, pwd.data, PDB_SET)) { + DEBUG(5, ("gums_object_to_sam_account: unable to set nt password")); + data_blob_clear_free(&pwd); + ret = NT_STATUS_UNSUCCESSFUL; + goto error; + } + data_blob_clear_free(&pwd); + pwd = gums_get_user_lm_pwd(go); + if (!pdb_set_lanman_passwd(sa, pwd.data, PDB_SET)) { + DEBUG(5, ("gums_object_to_sam_account: unable to set lanman password")); + data_blob_clear_free(&pwd); + ret = NT_STATUS_UNSUCCESSFUL; + goto error; + } + data_blob_clear_free(&pwd); + + BOOL_SET_OR_FAIL(pdb_set_unknown_3(sa, gums_get_user_unknown_3(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_bad_password_count(sa, gums_get_user_bad_password_count(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_unknown_6(sa, gums_get_user_unknown_6(go), PDB_SET), error); + BOOL_SET_OR_FAIL(pdb_set_hours(sa, gums_get_user_hours(go), PDB_SET), error); + + return NT_STATUS_OK; + +error: + if (sa && (sa->free_fn)) { + sa->free_fn(&sa); + } + + return ret; +} + +static NTSTATUS sam_account_to_gums_object(GUMS_OBJECT *go, SAM_ACCOUNT *sa) +{ + NTSTATUS ret; + NTTIME nt_time; + DATA_BLOB pwd; + + if (!go || !sa) + return NT_STATUS_INVALID_PARAMETER; + +/* + ret = gums_create_object(go, GUMS_OBJ_NORMAL_USER); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("sam_account_to_gums_object: error occurred while creating gums object!\n")); + goto error; + } +*/ + + /* sec_desc */ + + SET_OR_FAIL(gums_set_object_name(go, pdb_get_username(sa)), error); + + SET_OR_FAIL(gums_set_object_sid(go, pdb_get_user_sid(sa)), error); + SET_OR_FAIL(gums_set_user_pri_group(go, pdb_get_group_sid(sa)), error); + + if (pdb_get_acct_desc(sa)) + SET_OR_FAIL(gums_set_object_description(go, pdb_get_acct_desc(sa)), error); + if (pdb_get_fullname(sa)) + SET_OR_FAIL(gums_set_user_fullname(go, pdb_get_fullname(sa)), error); + if (pdb_get_homedir(sa)) + SET_OR_FAIL(gums_set_user_homedir(go, pdb_get_homedir(sa)), error); + if (pdb_get_dir_drive(sa)) + SET_OR_FAIL(gums_set_user_dir_drive(go, pdb_get_dir_drive(sa)), error); + if (pdb_get_logon_script(sa)) + SET_OR_FAIL(gums_set_user_logon_script(go, pdb_get_logon_script(sa)), error); + if (pdb_get_profile_path(sa)) + SET_OR_FAIL(gums_set_user_profile_path(go, pdb_get_profile_path(sa)), error); + if (pdb_get_workstations(sa)) + SET_OR_FAIL(gums_set_user_workstations(go, pdb_get_workstations(sa)), error); + if (pdb_get_unknown_str(sa)) + SET_OR_FAIL(gums_set_user_unknown_str(go, pdb_get_unknown_str(sa)), error); + if (pdb_get_munged_dial(sa)) + SET_OR_FAIL(gums_set_user_munged_dial(go, pdb_get_munged_dial(sa)), error); + SET_OR_FAIL(gums_set_user_logon_divs(go, pdb_get_logon_divs(sa)), error); + if (pdb_get_hours(sa)) + SET_OR_FAIL(gums_set_user_hours(go, pdb_get_hours_len(sa), pdb_get_hours(sa)), error); + SET_OR_FAIL(gums_set_user_unknown_3(go, pdb_get_unknown_3(sa)), error); + SET_OR_FAIL(gums_set_user_bad_password_count(go, pdb_get_bad_password_count(sa)), error); + SET_OR_FAIL(gums_set_user_unknown_6(go, pdb_get_unknown_6(sa)), error); + + unix_to_nt_time(&nt_time, pdb_get_logon_time(sa)); + SET_OR_FAIL(gums_set_user_logon_time(go, nt_time), error); + unix_to_nt_time(&nt_time, pdb_get_logoff_time(sa)); + SET_OR_FAIL(gums_set_user_logoff_time(go, nt_time), error); + unix_to_nt_time(&nt_time, pdb_get_kickoff_time(sa)); + SET_OR_FAIL(gums_set_user_kickoff_time(go, nt_time), error); + unix_to_nt_time(&nt_time, pdb_get_pass_last_set_time(sa)); + SET_OR_FAIL(gums_set_user_pass_last_set_time(go, nt_time), error); + unix_to_nt_time(&nt_time, pdb_get_pass_can_change_time(sa)); + SET_OR_FAIL(gums_set_user_pass_can_change_time(go, nt_time), error); + unix_to_nt_time(&nt_time, pdb_get_pass_must_change_time(sa)); + SET_OR_FAIL(gums_set_user_pass_must_change_time(go, nt_time), error); + + pwd = data_blob(pdb_get_nt_passwd(sa), NT_HASH_LEN); + ret = gums_set_user_nt_pwd(go, pwd); + data_blob_clear_free(&pwd); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(5, ("sam_account_to_gums_object: failed to set nt password!\n")); + goto error; + } + pwd = data_blob(pdb_get_lanman_passwd(sa), LM_HASH_LEN); + ret = gums_set_user_lm_pwd(go, pwd); + data_blob_clear_free(&pwd); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(5, ("sam_account_to_gums_object: failed to set lanman password!\n")); + goto error; + } + + SET_OR_FAIL(gums_set_user_acct_ctrl(go, pdb_get_acct_ctrl(sa)), error); + + return NT_STATUS_OK; + +error: + gums_reset_object(go); + return ret; +} + +static NTSTATUS gums_setsampwent(struct pdb_methods *methods, BOOL update) +{ + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + return ggwd->fns->enumerate_objects_start(&(ggwd->handle), NULL, GUMS_OBJ_NORMAL_USER); +} + +static NTSTATUS gums_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *account) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->enumerate_objects_get_next(&go, ggwd->handle))) { + return ret; + } + + ret = gums_object_to_sam_account(account, go); + + gums_destroy_object(&go); + return ret; +} + +static void gums_endsampwent(struct pdb_methods *methods) +{ + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + ggwd->fns->enumerate_objects_stop(ggwd->handle); +} + +/****************************************************************** + Lookup a name in the SAM database + ******************************************************************/ + +static NTSTATUS gums_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *account, const char *name) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!account || !name) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_name(&go, name, GUMS_OBJ_NORMAL_USER))) { + DEBUG(10, ("gums_getsampwnam: unable to find account with name %s", name)); + return ret; + } + + ret = gums_object_to_sam_account(account, go); + + gums_destroy_object(&go); + return ret; +} + +/*************************************************************************** + Search by SID + **************************************************************************/ + +static NTSTATUS gums_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT *account, const DOM_SID *sid) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!account || !sid) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_sid(&go, sid, GUMS_OBJ_NORMAL_USER))) { + DEBUG(10, ("gums_getsampwsid: unable to find account with sid %s", sid_string_static(sid))); + return ret; + } + + ret = gums_object_to_sam_account(account, go); + + gums_destroy_object(&go); + return ret; +} + +/*************************************************************************** + Search by rid + **************************************************************************/ + +static NTSTATUS gums_getsampwrid (struct pdb_methods *methods, + SAM_ACCOUNT *account, uint32 rid) +{ + DOM_SID sid; + + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, rid); + gums_getsampwsid(methods, account, &sid); +} + + +/*************************************************************************** + Updates a SAM_ACCOUNT + + This isn't a particulary practical option for pdb_guest. We certainly don't + want to twidde the filesystem, so what should we do? + + Current plan is to transparently add the account. It should appear + as if the pdb_guest version was modified, but its actually stored somehwere. + ****************************************************************************/ + +static NTSTATUS gums_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!account) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = gums_create_object(&go, GUMS_OBJ_NORMAL_USER))) { + DEBUG(0, ("gums_add_sam_account: error occurred while creating gums object!\n")); + return ret; + } + + if (!NT_STATUS_IS_OK(ret = sam_account_to_gums_object(go, account))) { + DEBUG(0, ("gums_add_sam_account: error occurred while converting object!\n")); + goto done; + } + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->set_object(go))) { + DEBUG(0, ("gums_add_sam_account: unable to store account!\n")); + goto done; + } + +done: + gums_destroy_object(&go); + return ret; +} + +static NTSTATUS gums_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!account) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_sid(&go, pdb_get_user_sid(account), GUMS_OBJ_NORMAL_USER))) { + DEBUG(0, ("gums_update_sam_account: update on invalid account!\n")); + return ret; + } + + if (!NT_STATUS_IS_OK(ret = sam_account_to_gums_object(go, account))) { + DEBUG(0, ("gums_update_sam_account: error occurred while converting object!\n")); + goto done; + } + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->set_object(go))) { + DEBUG(0, ("gums_update_sam_account: unable to store account!\n")); + goto done; + } + +done: + gums_destroy_object(&go); + return ret; +} + +static NTSTATUS gums_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account) +{ + NTSTATUS ret; + struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data); + + if (!account) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = ggwd->fns->delete_object(pdb_get_user_sid(account)))) { + DEBUG(0, ("gums_add_sam_account: unable to store account!\n")); + } + + return ret; +} + + +static void free_gw_private_data(void **vp) +{ + struct gums_gw_data *ggwd = (struct gums_gw_data *)vp; + ggwd->fns->free_private_data(&(ggwd->fns->private_data)); + ggwd->fns = NULL; + ggwd->handle = NULL; + SAFE_FREE(vp); +} + +NTSTATUS pdb_init_gums_gateway(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS ret; + struct gums_gw_data *ggwd; + + if (!pdb_context) { + DEBUG(0, ("invalid pdb_context specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(ret = gums_setup_backend(lp_gums_backend()))) { + DEBUG(0, ("pdb_init_gums_gateway: initialization error!\n")); + return ret; + } + + ggwd = (struct gums_gw_data *)malloc(sizeof(struct gums_gw_data)); + if (!ggwd) + return NT_STATUS_NO_MEMORY; + memset(ggwd, 0, sizeof(struct gums_gw_data)); + + if (!NT_STATUS_IS_OK(ret = get_gums_fns(&(ggwd->fns)))) { + goto error; + } + + if (!NT_STATUS_IS_OK(ret = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + goto error; + } + + (*pdb_method)->name = "gums_gateway"; + + (*pdb_method)->setsampwent = gums_setsampwent; + (*pdb_method)->getsampwent = gums_getsampwent; + (*pdb_method)->endsampwent = gums_endsampwent; + (*pdb_method)->getsampwnam = gums_getsampwnam; + (*pdb_method)->getsampwsid = gums_getsampwsid; + (*pdb_method)->add_sam_account = gums_add_sam_account; + (*pdb_method)->update_sam_account = gums_update_sam_account; + (*pdb_method)->delete_sam_account = gums_delete_sam_account; + + /* we should do no group mapping here */ +/* (*pdb_method)->getgrsid = gums_getgrsid; + (*pdb_method)->getgrgid = gums_getgrgid; + (*pdb_method)->getgrnam = gums_getgrnam; + (*pdb_method)->add_group_mapping_entry = gums_add_group_mapping_entry; + (*pdb_method)->update_group_mapping_entry = gums_update_group_mapping_entry; + (*pdb_method)->delete_group_mapping_entry = gums_delete_group_mapping_entry; + (*pdb_method)->enum_group_mapping = gums_enum_group_mapping;*/ + + /* we do not handle groups in guest backend */ +/* FIXME + (*pdb_method)->get_group_info_by_sid = gums_get_group_info_by_sid; + (*pdb_method)->get_group_list = gums_get_group_list; + (*pdb_method)->get_group_sids = gums_get_group_sids; + (*pdb_method)->add_group = gums_add_group; + (*pdb_method)->update_group = gums_update_group; + (*pdb_method)->delete_group = gums_delete_group; + (*pdb_method)->add_sid_to_group = gums_add_sid_to_group; + (*pdb_method)->remove_sid_from_group = gums_remove_sid_from_group; + (*pdb_method)->get_group_info_by_name = gums_get_group_info_by_name; + (*pdb_method)->get_group_info_by_nt_name = gums_get_group_info_by_nt_name; + (*pdb_method)->get_group_uids = gums_get_group_uids; +*/ + + (*pdb_method)->private_data = ggwd; + (*pdb_method)->free_private_data = free_gw_private_data; + + return NT_STATUS_OK; + +error: + SAFE_FREE(ggwd); + return ret; +} + +NTSTATUS pdb_gums_init(void) +{ + return smb_register_passdb(PASSDB_INTERFACE_VERSION, "gums", pdb_init_gums_gateway); +} + diff --git a/source3/sam/gumm_tdb.c b/source3/sam/gumm_tdb.c deleted file mode 100644 index 2623180afb..0000000000 --- a/source3/sam/gumm_tdb.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * SMB parameters and setup - * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Simo Sorce 2000-2002 - * Copyright (C) Gerald Carter 2000 - * Copyright (C) Jeremy Allison 2001 - * Copyright (C) Andrew Bartlett 2002 - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -#include "tdbsam2.h" -#include "tdbsam2_parse_info.h" - -static int tdbgumm_debug_level = DBGC_ALL; -#undef DBGC_CLASS -#define DBGC_CLASS tdbgumm_debug_level - -#define TDBSAM_VERSION 20021215 -#define TDB_FILE_NAME "tdbsam2.tdb" -#define NAMEPREFIX "NAME_" -#define SIDPREFIX "SID_" -#define PRIVILEGEPREFIX "PRIV_" - -#define TDB_FORMAT_STRING "ddB" - -#define TALLOC_CHECK(ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: Out of memory!\n", FUNCTION_MACRO)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) -#define SET_OR_FAIL(func, label) do { if (NT_STATUS_IS_ERR(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0) - -struct tdbsam2_enum_objs { - uint32 type; - fstring dom_sid; - TDB_CONTEXT *db; - TDB_DATA key; - struct tdbsam2_enum_objs *next; -}; - -union tdbsam2_data { - struct tdbsam2_domain_data *domain; - struct tdbsam2_user_data *user; - struct tdbsam2_group_data *group; -}; - -struct tdbsam2_object { - uint32 type; - uint32 version; - union tdbsam2_data data; -}; - -static TDB_CONTEXT *tdbsam2_db; - -struct tdbsam2_enum_objs **teo_handlers; - -static NTSTATUS init_tdbsam2_object_from_buffer(struct tdbsam2_object *object, TALLOC_CTX *mem_ctx, char *buffer, int size) -{ - - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - int iret; - char *obj_data; - int data_size = 0; - int len; - - len = tdb_unpack (buffer, size, TDB_FORMAT_STRING, - &(object->version), - &(object->type), - &data_size, &obj_data); - - if (len == -1) - goto done; - - /* version is checked inside this function so that backward compatibility code can be - called eventually. - this way we can easily handle database format upgrades */ - if (object->version != TDBSAM_VERSION) { - DEBUG(3,("init_tdbsam2_object_from_buffer: Error, db object has wrong tdbsam version!\n")); - goto done; - } - - /* be sure the string is terminated before trying to parse it */ - if (obj_data[data_size - 1] != '\0') - obj_data[data_size - 1] = '\0'; - - switch (object->type) { - case GUMS_OBJ_DOMAIN: - object->data.domain = (struct tdbsam2_domain_data *)talloc(mem_ctx, sizeof(struct tdbsam2_domain_data)); - TALLOC_CHECK(object->data.domain, ret, done); - memset(object->data.domain, 0, sizeof(struct tdbsam2_domain_data)); - - iret = gen_parse(mem_ctx, pinfo_tdbsam2_domain_data, (char *)(object->data.domain), obj_data); - break; - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - object->data.group = (struct tdbsam2_group_data *)talloc(mem_ctx, sizeof(struct tdbsam2_group_data)); - TALLOC_CHECK(object->data.group, ret, done); - memset(object->data.group, 0, sizeof(struct tdbsam2_group_data)); - - iret = gen_parse(mem_ctx, pinfo_tdbsam2_group_data, (char *)(object->data.group), obj_data); - break; - case GUMS_OBJ_NORMAL_USER: - object->data.user = (struct tdbsam2_user_data *)talloc(mem_ctx, sizeof(struct tdbsam2_user_data)); - TALLOC_CHECK(object->data.user, ret, done); - memset(object->data.user, 0, sizeof(struct tdbsam2_user_data)); - - iret = gen_parse(mem_ctx, pinfo_tdbsam2_user_data, (char *)(object->data.user), obj_data); - break; - default: - DEBUG(3,("init_tdbsam2_object_from_buffer: Error, wrong object type number!\n")); - goto done; - } - - if (iret != 0) { - DEBUG(0,("init_tdbsam2_object_from_buffer: Fatal Error! Unable to parse object!\n")); - DEBUG(0,("init_tdbsam2_object_from_buffer: DB Corrupted ?")); - goto done; - } - - ret = NT_STATUS_OK; -done: - SAFE_FREE(obj_data); - return ret; -} - -static NTSTATUS init_buffer_from_tdbsam2_object(char **buffer, size_t *len, TALLOC_CTX *mem_ctx, struct tdbsam2_object *object) -{ - - NTSTATUS ret; - char *buf1 = NULL; - size_t buflen; - - if (!buffer) - return NT_STATUS_INVALID_PARAMETER; - - switch (object->type) { - case GUMS_OBJ_DOMAIN: - buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_domain_data, (char *)(object->data.domain), 0); - break; - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_group_data, (char *)(object->data.group), 0); - break; - case GUMS_OBJ_NORMAL_USER: - buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_user_data, (char *)(object->data.user), 0); - break; - default: - DEBUG(3,("init_buffer_from_tdbsam2_object: Error, wrong object type number!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (buf1 == NULL) { - DEBUG(0, ("init_buffer_from_tdbsam2_object: Fatal Error! Unable to dump object!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - buflen = tdb_pack(NULL, 0, TDB_FORMAT_STRING, - TDBSAM_VERSION, - object->type, - strlen(buf1) + 1, buf1); - - *buffer = talloc(mem_ctx, buflen); - TALLOC_CHECK(*buffer, ret, done); - - *len = tdb_pack(*buffer, buflen, TDB_FORMAT_STRING, - TDBSAM_VERSION, - object->type, - strlen(buf1) + 1, buf1); - - if (*len != buflen) { - DEBUG(0, ("init_tdb_data_from_tdbsam2_object: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", - buflen, *len)); - *buffer = NULL; - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - ret = NT_STATUS_OK; -done: - return ret; -} - -static NTSTATUS opentdb(void) -{ - if (!tdbsam2_db) { - pstring tdbfile; - get_private_directory(tdbfile); - pstrcat(tdbfile, "/"); - pstrcat(tdbfile, TDB_FILE_NAME); - - tdbsam2_db = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600); - if (!tdbsam2_db) - { - DEBUG(0, ("opentdb: Unable to open database (%s)!\n", tdbfile)); - return NT_STATUS_UNSUCCESSFUL; - } - } - - return NT_STATUS_OK; -} - -static NTSTATUS get_object_by_sid(TALLOC_CTX *mem_ctx, struct tdbsam2_object *obj, const DOM_SID *sid) -{ - NTSTATUS ret; - TDB_DATA data, key; - fstring keystr; - - if (!obj || !mem_ctx || !sid) - return NT_STATUS_INVALID_PARAMETER; - - if (NT_STATUS_IS_ERR(ret = opentdb())) { - return ret; - } - - slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid)); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(tdbsam2_db, key); - if (!data.dptr) { - DEBUG(5, ("get_object_by_sid: Error fetching database, domain entry not found!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db))); - DEBUGADD(5, (" Key: %s\n", keystr)); - return NT_STATUS_UNSUCCESSFUL; - } - - if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(obj, mem_ctx, data.dptr, data.dsize))) { - SAFE_FREE(data.dptr); - DEBUG(0, ("get_object_by_sid: Error fetching database, malformed entry!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - SAFE_FREE(data.dptr); - - return NT_STATUS_OK; - -} - -static NTSTATUS get_object_by_name(TALLOC_CTX *mem_ctx, struct tdbsam2_object *obj, const char* name) -{ - - NTSTATUS ret; - TDB_DATA data, key; - fstring keystr; - fstring objname; - DOM_SID sid; - char *obj_sidstr; - int obj_version, obj_type, obj_sidstr_len, len; - - if (!obj || !mem_ctx || !name) - return NT_STATUS_INVALID_PARAMETER; - - if (NT_STATUS_IS_ERR(ret = opentdb())) { - return ret; - } - - fstrcpy(objname, name); - strlower(objname); - - slprintf(keystr, sizeof(keystr)-1, "%s%s", NAMEPREFIX, objname); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(tdbsam2_db, key); - if (!data.dptr) { - DEBUG(5, ("get_object_by_name: Error fetching database, domain entry not found!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db))); - DEBUGADD(5, (" Key: %s\n", keystr)); - return NT_STATUS_UNSUCCESSFUL; - } - - len = tdb_unpack(data.dptr, data.dsize, TDB_FORMAT_STRING, - &obj_version, - &obj_type, - &obj_sidstr_len, &obj_sidstr); - - SAFE_FREE(data.dptr); - - if (len == -1 || obj_version != TDBSAM_VERSION || obj_sidstr_len <= 0) { - DEBUG(5, ("get_object_by_name: Error unpacking database object!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!string_to_sid(&sid, obj_sidstr)) { - DEBUG(5, ("get_object_by_name: Error invalid sid string found in database object!\n")); - SAFE_FREE(obj_sidstr); - return NT_STATUS_UNSUCCESSFUL; - } - SAFE_FREE(obj_sidstr); - - return get_object_by_sid(mem_ctx, obj, &sid); -} - -static NTSTATUS store_object(TALLOC_CTX *mem_ctx, struct tdbsam2_object *object, BOOL new_obj) -{ - - NTSTATUS ret; - TDB_DATA data, key, key2; - fstring keystr; - fstring namestr; - int flag, r; - - if (NT_STATUS_IS_ERR(ret = opentdb())) { - return ret; - } - - if (new_obj) { - flag = TDB_INSERT; - } else { - flag = TDB_MODIFY; - } - - ret = init_buffer_from_tdbsam2_object(&(data.dptr), &(data.dsize), mem_ctx, object); - if (NT_STATUS_IS_ERR(ret)) - return ret; - - switch (object->type) { - case GUMS_OBJ_DOMAIN: - slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.domain->dom_sid)); - slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.domain->name); - break; - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.group->group_sid)); - slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.group->name); - break; - case GUMS_OBJ_NORMAL_USER: - slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.user->user_sid)); - slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.user->name); - break; - default: - return NT_STATUS_UNSUCCESSFUL; - } - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - if ((r = tdb_store(tdbsam2_db, key, data, flag)) != TDB_SUCCESS) { - DEBUG(0, ("store_object: Unable to modify SAM!\n")); - DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam2_db))); - DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr)); - if (r == TDB_ERR_EXISTS) return NT_STATUS_UNSUCCESSFUL; - return NT_STATUS_INTERNAL_DB_ERROR; - } - - key2.dptr = namestr; - key2.dsize = strlen(namestr) + 1; - - if ((r = tdb_store(tdbsam2_db, key2, key, flag)) != TDB_SUCCESS) { - DEBUG(0, ("store_object: Unable to modify SAM!\n")); - DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam2_db))); - DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr)); - if (r == TDB_ERR_EXISTS) return NT_STATUS_UNSUCCESSFUL; - return NT_STATUS_INTERNAL_DB_ERROR; - } -/* TODO: update the general database counter */ -/* TODO: update this entry counter too */ - - return NT_STATUS_OK; -} - -static NTSTATUS get_next_sid(TALLOC_CTX *mem_ctx, DOM_SID **sid) -{ - NTSTATUS ret; - struct tdbsam2_object obj; - DOM_SID *dom_sid = get_global_sam_sid(); - uint32 new_rid; - -/* TODO: LOCK DOMAIN OBJECT */ - ret = get_object_by_sid(mem_ctx, &obj, dom_sid); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("get_next_sid: unable to get root Domain object!\n")); - ret = NT_STATUS_INTERNAL_DB_ERROR; - goto error; - } - - new_rid = obj.data.domain->next_rid; - - /* Increment the RID Counter */ - obj.data.domain->next_rid++; - - /* Store back Domain object */ - ret = store_object(mem_ctx, &obj, False); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("get_next_sid: unable to update root Domain object!\n")); - ret = NT_STATUS_INTERNAL_DB_ERROR; - goto error; - } -/* TODO: UNLOCK DOMAIN OBJECT */ - - *sid = sid_dup_talloc(mem_ctx, dom_sid); - TALLOC_CHECK(*sid, ret, error); - - if (!sid_append_rid(*sid, new_rid)) { - DEBUG(0, ("get_next_sid: unable to build new SID !?!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto error; - } - - return NT_STATUS_OK; - -error: - return ret; -} - -static NTSTATUS user_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_user_data *userdata) -{ - NTSTATUS ret; - - if (!object || !userdata) { - DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL pointers are accepted here!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* userdata->xcounter */ - /* userdata->sec_desc */ - - SET_OR_FAIL(gums_set_object_sid(*object, userdata->user_sid), error); - SET_OR_FAIL(gums_set_object_name(*object, userdata->name), error); - - SET_OR_FAIL(gums_set_user_pri_group(*object, userdata->group_sid), error); - - if (userdata->description) - SET_OR_FAIL(gums_set_object_description(*object, userdata->description), error); - - if (userdata->full_name) - SET_OR_FAIL(gums_set_user_fullname(*object, userdata->full_name), error); - - if (userdata->home_dir) - SET_OR_FAIL(gums_set_user_homedir(*object, userdata->home_dir), error); - - if (userdata->dir_drive) - SET_OR_FAIL(gums_set_user_dir_drive(*object, userdata->dir_drive), error); - - if (userdata->logon_script) - SET_OR_FAIL(gums_set_user_logon_script(*object, userdata->logon_script), error); - - if (userdata->profile_path) - SET_OR_FAIL(gums_set_user_profile_path(*object, userdata->profile_path), error); - - if (userdata->workstations) - SET_OR_FAIL(gums_set_user_workstations(*object, userdata->workstations), error); - - if (userdata->unknown_str) - SET_OR_FAIL(gums_set_user_unknown_str(*object, userdata->unknown_str), error); - - if (userdata->munged_dial) - SET_OR_FAIL(gums_set_user_munged_dial(*object, userdata->munged_dial), error); - - SET_OR_FAIL(gums_set_user_logon_divs(*object, userdata->logon_divs), error); - SET_OR_FAIL(gums_set_user_hours_len(*object, userdata->hours_len), error); - - if (userdata->hours) - SET_OR_FAIL(gums_set_user_hours(*object, userdata->hours), error); - - SET_OR_FAIL(gums_set_user_unknown_3(*object, userdata->unknown_3), error); - SET_OR_FAIL(gums_set_user_bad_password_count(*object, userdata->bad_password_count), error); - SET_OR_FAIL(gums_set_user_unknown_6(*object, userdata->unknown_6), error); - - SET_OR_FAIL(gums_set_user_logon_time(*object, *(userdata->logon_time)), error); - SET_OR_FAIL(gums_set_user_logoff_time(*object, *(userdata->logoff_time)), error); - SET_OR_FAIL(gums_set_user_kickoff_time(*object, *(userdata->kickoff_time)), error); - SET_OR_FAIL(gums_set_user_pass_last_set_time(*object, *(userdata->pass_last_set_time)), error); - SET_OR_FAIL(gums_set_user_pass_can_change_time(*object, *(userdata->pass_can_change_time)), error); - SET_OR_FAIL(gums_set_user_pass_must_change_time(*object, *(userdata->pass_must_change_time)), error); - - ret = NT_STATUS_OK; - return ret; - -error: - talloc_destroy((*object)->mem_ctx); - *object = NULL; - return ret; -} - -static NTSTATUS group_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_group_data *groupdata) -{ - NTSTATUS ret; - - if (!object || !groupdata) { - DEBUG(0, ("tdbsam2_group_data_to_gums_object: no NULL pointers are accepted here!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* groupdata->xcounter */ - /* groupdata->sec_desc */ - - SET_OR_FAIL(gums_set_object_sid(*object, groupdata->group_sid), error); - SET_OR_FAIL(gums_set_object_name(*object, groupdata->name), error); - - if (groupdata->description) - SET_OR_FAIL(gums_set_object_description(*object, groupdata->description), error); - - if (groupdata->count) - SET_OR_FAIL(gums_set_group_members(*object, groupdata->count, groupdata->members), error); - - ret = NT_STATUS_OK; - return ret; - -error: - talloc_destroy((*object)->mem_ctx); - *object = NULL; - return ret; -} - -static NTSTATUS domain_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_domain_data *domdata) -{ - - NTSTATUS ret; - - if (!object || !*object || !domdata) { - DEBUG(0, ("tdbsam2_domain_data_to_gums_object: no NULL pointers are accepted here!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* domdata->xcounter */ - /* domdata->sec_desc */ - - SET_OR_FAIL(gums_set_object_sid(*object, domdata->dom_sid), error); - SET_OR_FAIL(gums_set_object_name(*object, domdata->name), error); - - if (domdata->description) - SET_OR_FAIL(gums_set_object_description(*object, domdata->description), error); - - ret = NT_STATUS_OK; - return ret; - -error: - talloc_destroy((*object)->mem_ctx); - *object = NULL; - return ret; -} - -static NTSTATUS data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_object *data) -{ - - NTSTATUS ret; - - if (!object || !data) { - DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL structure pointers are accepted here!\n")); - ret = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - ret = gums_create_object(object, data->type); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(5, ("tdbsam2_user_data_to_gums_object: error creating gums object!\n")); - goto done; - } - - switch (data->type) { - case GUMS_OBJ_DOMAIN: - ret = domain_data_to_gums_object(object, data->data.domain); - break; - - case GUMS_OBJ_NORMAL_USER: - ret = user_data_to_gums_object(object, data->data.user); - break; - - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - ret = group_data_to_gums_object(object, data->data.group); - break; - - default: - ret = NT_STATUS_UNSUCCESSFUL; - } - -done: - return ret; -} - - -/* GUMM object functions */ - -static NTSTATUS tdbsam2_get_domain_sid(DOM_SID *sid, const char* name) -{ - - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - fstring domname; - - if (!sid || !name) - return NT_STATUS_INVALID_PARAMETER; - - mem_ctx = talloc_init("tdbsam2_get_domain_sid"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_new_object: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (NT_STATUS_IS_ERR(ret = opentdb())) { - goto done; - } - - fstrcpy(domname, name); - strlower(domname); - - ret = get_object_by_name(mem_ctx, &obj, domname); - - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("tdbsam2_get_domain_sid: Error fetching database!\n")); - goto done; - } - - if (obj.type != GUMS_OBJ_DOMAIN) { - DEBUG(5, ("tdbsam2_get_domain_sid: Requested object is not a domain!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - sid_copy(sid, obj.data.domain->dom_sid); - - ret = NT_STATUS_OK; - -done: - talloc_destroy(mem_ctx); - return ret; -} - -static NTSTATUS tdbsam2_set_domain_sid (const DOM_SID *sid, const char *name) -{ - - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - fstring domname; - - if (!sid || !name) - return NT_STATUS_INVALID_PARAMETER; - - mem_ctx = talloc_init("tdbsam2_set_domain_sid"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_new_object: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (tdbsam2_db == NULL) { - if (NT_STATUS_IS_ERR(ret = opentdb())) { - goto done; - } - } - - fstrcpy(domname, name); - strlower(domname); - -/* TODO: we need to lock this entry until updated! */ - - ret = get_object_by_name(mem_ctx, &obj, domname); - - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("tdbsam2_get_domain_sid: Error fetching database!\n")); - goto done; - } - - if (obj.type != GUMS_OBJ_DOMAIN) { - DEBUG(5, ("tdbsam2_get_domain_sid: Requested object is not a domain!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - sid_copy(obj.data.domain->dom_sid, sid); - - ret = store_object(mem_ctx, &obj, False); - -done: -/* TODO: unlock here */ - if (mem_ctx) talloc_destroy(mem_ctx); - return ret; -} - -/* TODO */ - NTSTATUS (*get_sequence_number) (void); - - -extern DOM_SID global_sid_NULL; - -static NTSTATUS tdbsam2_new_object(DOM_SID *sid, const char *name, const int obj_type) -{ - - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - NTTIME zero_time = {0,0}; - const char *defpw = "NOPASSWORDXXXXXX"; - uint8 defhours[21] = {255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; - - if (!sid || !name) { - DEBUG(0, ("tdbsam2_new_object: no NULL pointers are accepted here!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - mem_ctx = talloc_init("tdbsam2_new_object"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_new_object: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - obj.type = obj_type; - obj.version = TDBSAM_VERSION; - - switch (obj_type) { - case GUMS_OBJ_NORMAL_USER: - obj.data.user = (struct tdbsam2_user_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_user_data)); - TALLOC_CHECK(obj.data.user, ret, done); - - get_next_sid(mem_ctx, &(obj.data.user->user_sid)); - TALLOC_CHECK(obj.data.user->user_sid, ret, done); - sid_copy(sid, obj.data.user->user_sid); - - obj.data.user->name = talloc_strdup(mem_ctx, name); - TALLOC_CHECK(obj.data.user, ret, done); - - obj.data.user->xcounter = 1; - /*obj.data.user->sec_desc*/ - obj.data.user->description = ""; - obj.data.user->group_sid = &global_sid_NULL; - obj.data.user->logon_time = &zero_time; - obj.data.user->logoff_time = &zero_time; - obj.data.user->kickoff_time = &zero_time; - obj.data.user->pass_last_set_time = &zero_time; - obj.data.user->pass_can_change_time = &zero_time; - obj.data.user->pass_must_change_time = &zero_time; - - obj.data.user->full_name = ""; - obj.data.user->home_dir = ""; - obj.data.user->dir_drive = ""; - obj.data.user->logon_script = ""; - obj.data.user->profile_path = ""; - obj.data.user->workstations = ""; - obj.data.user->unknown_str = ""; - obj.data.user->munged_dial = ""; - - obj.data.user->lm_pw_ptr = defpw; - obj.data.user->nt_pw_ptr = defpw; - - obj.data.user->logon_divs = 168; - obj.data.user->hours_len = 21; - obj.data.user->hours = &defhours; - - obj.data.user->unknown_3 = 0x00ffffff; - obj.data.user->bad_password_count = 0x00020000; - obj.data.user->unknown_6 = 0x000004ec; - break; - - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - obj.data.group = (struct tdbsam2_group_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_group_data)); - TALLOC_CHECK(obj.data.group, ret, done); - - get_next_sid(mem_ctx, &(obj.data.group->group_sid)); - TALLOC_CHECK(obj.data.group->group_sid, ret, done); - sid_copy(sid, obj.data.group->group_sid); - - obj.data.group->name = talloc_strdup(mem_ctx, name); - TALLOC_CHECK(obj.data.group, ret, done); - - obj.data.group->xcounter = 1; - /*obj.data.group->sec_desc*/ - obj.data.group->description = ""; - - break; - - case GUMS_OBJ_DOMAIN: - - /* FIXME: should we check against global_sam_sid to make it impossible - to store more than one domain ? */ - - obj.data.domain = (struct tdbsam2_domain_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_domain_data)); - TALLOC_CHECK(obj.data.domain, ret, done); - - obj.data.domain->dom_sid = sid_dup_talloc(mem_ctx, get_global_sam_sid()); - TALLOC_CHECK(obj.data.domain->dom_sid, ret, done); - sid_copy(sid, obj.data.domain->dom_sid); - - obj.data.domain->name = talloc_strdup(mem_ctx, name); - TALLOC_CHECK(obj.data.domain, ret, done); - - obj.data.domain->xcounter = 1; - /*obj.data.domain->sec_desc*/ - obj.data.domain->next_rid = 0x3e9; - obj.data.domain->description = ""; - - ret = NT_STATUS_OK; - break; - - default: - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - ret = store_object(mem_ctx, &obj, True); - -done: - talloc_destroy(mem_ctx); - return ret; -} - -static NTSTATUS tdbsam2_delete_object(const DOM_SID *sid) -{ - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - TDB_DATA data, key; - fstring keystr; - - if (!sid) { - DEBUG(0, ("tdbsam2_delete_object: no NULL pointers are accepted here!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - mem_ctx = talloc_init("tdbsam2_delete_object"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_delete_object: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (tdbsam2_db == NULL) { - if (NT_STATUS_IS_ERR(ret = opentdb())) { - goto done; - } - } - - slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid)); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(tdbsam2_db, key); - if (!data.dptr) { - DEBUG(5, ("tdbsam2_delete_object: Error fetching database, SID entry not found!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db))); - DEBUGADD(5, (" Key: %s\n", keystr)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - if (tdb_delete(tdbsam2_db, key) != TDB_SUCCESS) { - DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db))); - DEBUGADD(5, (" Key: %s\n", keystr)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(&obj, mem_ctx, data.dptr, data.dsize))) { - SAFE_FREE(data.dptr); - DEBUG(0, ("tdbsam2_delete_object: Error fetching database, malformed entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - switch (obj.type) { - case GUMS_OBJ_DOMAIN: - /* TODO: SHOULD WE ALLOW TO DELETE DOMAINS ? */ - slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.domain->name); - break; - case GUMS_OBJ_GROUP: - case GUMS_OBJ_ALIAS: - slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.group->name); - break; - case GUMS_OBJ_NORMAL_USER: - slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.user->name); - break; - default: - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - if (tdb_delete(tdbsam2_db, key) != TDB_SUCCESS) { - DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db))); - DEBUGADD(5, (" Key: %s\n", keystr)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - -/* TODO: update the general database counter */ - -done: - SAFE_FREE(data.dptr); - talloc_destroy(mem_ctx); - return ret; -} - -static NTSTATUS tdbsam2_get_object_from_sid(GUMS_OBJECT **object, const DOM_SID *sid, const int obj_type) -{ - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - - if (!object || !sid) { - DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - mem_ctx = talloc_init("tdbsam2_get_object_from_sid"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_get_object_from_sid: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - ret = get_object_by_sid(mem_ctx, &obj, sid); - if (NT_STATUS_IS_ERR(ret) || (obj_type && obj.type != obj_type)) { - DEBUG(0, ("tdbsam2_get_object_from_sid: error fetching object or wrong object type!\n")); - goto done; - } - - ret = data_to_gums_object(object, &obj); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("tdbsam2_get_object_from_sid: error setting object data!\n")); - goto done; - } - -done: - talloc_destroy(mem_ctx); - return ret; -} - -static NTSTATUS tdbsam2_get_object_from_name(GUMS_OBJECT **object, const char *name, const int obj_type) -{ - NTSTATUS ret; - struct tdbsam2_object obj; - TALLOC_CTX *mem_ctx; - - if (!object || !name) { - DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - mem_ctx = talloc_init("tdbsam2_get_object_from_sid"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_get_object_from_sid: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - ret = get_object_by_name(mem_ctx, &obj, name); - if (NT_STATUS_IS_ERR(ret) || (obj_type && obj.type != obj_type)) { - DEBUG(0, ("tdbsam2_get_object_from_sid: error fetching object or wrong object type!\n")); - goto done; - } - - ret = data_to_gums_object(object, &obj); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(0, ("tdbsam2_get_object_from_sid: error setting object data!\n")); - goto done; - } - -done: - talloc_destroy(mem_ctx); - return ret; -} - - /* This function is used to get the list of all objects changed since base_time, it is - used to support PDC<->BDC synchronization */ - NTSTATUS (*get_updated_objects) (GUMS_OBJECT **objects, const NTTIME base_time); - -static NTSTATUS tdbsam2_enumerate_objects_start(void *handle, const DOM_SID *sid, const int obj_type) -{ - struct tdbsam2_enum_objs *teo, *t; - pstring tdbfile; - - teo = (struct tdbsam2_enum_objs *)calloc(1, sizeof(struct tdbsam2_enum_objs)); - if (!teo) { - DEBUG(0, ("tdbsam2_enumerate_objects_start: Out of Memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - teo->type = obj_type; - if (sid) { - sid_to_string(teo->dom_sid, sid); - } - - get_private_directory(tdbfile); - pstrcat(tdbfile, "/"); - pstrcat(tdbfile, TDB_FILE_NAME); - - teo->db = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!teo->db) - { - DEBUG(0, ("tdbsam2_enumerate_objects_start: Unable to open database (%s)!\n", tdbfile)); - SAFE_FREE(teo); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!teo_handlers) { - *teo_handlers = teo; - } else { - t = *teo_handlers; - while (t->next) { - t = t->next; - } - t->next = teo; - } - - handle = teo; - - teo->key = tdb_firstkey(teo->db); - - return NT_STATUS_OK; -} - -static NTSTATUS tdbsam2_enumerate_objects_get_next(GUMS_OBJECT **object, void *handle) -{ - NTSTATUS ret; - TALLOC_CTX *mem_ctx; - TDB_DATA data; - struct tdbsam2_enum_objs *teo; - struct tdbsam2_object obj; - const char *prefix = SIDPREFIX; - const int preflen = strlen(prefix); - - if (!object || !handle) { - DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - teo = (struct tdbsam2_enum_objs *)handle; - - mem_ctx = talloc_init("tdbsam2_enumerate_objects_get_next"); - if (!mem_ctx) { - DEBUG(0, ("tdbsam2_enumerate_objects_get_next: Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - while ((teo->key.dsize != 0)) { - int len, version, type, size; - char *ptr; - - if (strncmp(teo->key.dptr, prefix, preflen)) { - teo->key = tdb_nextkey(teo->db, teo->key); - continue; - } - - if (teo->dom_sid) { - if (strncmp(&(teo->key.dptr[preflen]), teo->dom_sid, strlen(teo->dom_sid))) { - teo->key = tdb_nextkey(teo->db, teo->key); - continue; - } - } - - data = tdb_fetch(teo->db, teo->key); - if (!data.dptr) { - DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error fetching database, SID entry not found!\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(teo->db))); - DEBUGADD(5, (" Key: %s\n", teo->key.dptr)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - len = tdb_unpack (data.dptr, data.dsize, TDB_FORMAT_STRING, - &version, - &type, - &size, &ptr); - - if (len == -1) { - DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error unable to unpack data!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - SAFE_FREE(ptr); - - if (teo->type && type != teo->type) { - SAFE_FREE(data.dptr); - data.dsize = 0; - teo->key = tdb_nextkey(teo->db, teo->key); - continue; - } - - break; - } - - if (data.dsize != 0) { - if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(&obj, mem_ctx, data.dptr, data.dsize))) { - SAFE_FREE(data.dptr); - DEBUG(0, ("tdbsam2_enumerate_objects_get_next: Error fetching database, malformed entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - SAFE_FREE(data.dptr); - } - - ret = data_to_gums_object(object, &obj); - -done: - talloc_destroy(mem_ctx); - return ret; -} - -static NTSTATUS tdbsam2_enumerate_objects_stop(void *handle) -{ - struct tdbsam2_enum_objs *teo, *t, *p; - - teo = (struct tdbsam2_enum_objs *)handle; - - if (*teo_handlers == teo) { - *teo_handlers = teo->next; - } else { - t = *teo_handlers; - while (t != teo) { - p = t; - t = t->next; - if (t == NULL) { - DEBUG(0, ("tdbsam2_enumerate_objects_stop: Error, handle not found!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - } - p = t->next; - } - - tdb_close(teo->db); - SAFE_FREE(teo); - - return NT_STATUS_OK; -} - - /* This function MUST be used ONLY by PDC<->BDC replication code or recovery tools. - Never use this function to update an object in the database, use set_object_values() */ - NTSTATUS (*set_object) (const GUMS_OBJECT *object); - - /* set object values function */ - NTSTATUS (*set_object_values) (DOM_SID *sid, uint32 count, GUMS_DATA_SET *data_set); - - /* Group related functions */ - NTSTATUS (*add_memberss_to_group) (const DOM_SID *group, const DOM_SID **members); - NTSTATUS (*delete_members_from_group) (const DOM_SID *group, const DOM_SID **members); - NTSTATUS (*enumerate_group_members) (DOM_SID **members, const DOM_SID *sid, const int type); - - NTSTATUS (*get_sid_groups) (DOM_SID **groups, const DOM_SID *sid); - - NTSTATUS (*lock_sid) (const DOM_SID *sid); - NTSTATUS (*unlock_sid) (const DOM_SID *sid); - - /* privileges related functions */ - - NTSTATUS (*add_members_to_privilege) (const LUID_ATTR *priv, const DOM_SID **members); - NTSTATUS (*delete_members_from_privilege) (const LUID_ATTR *priv, const DOM_SID **members); - NTSTATUS (*enumerate_privilege_members) (DOM_SID **members, const LUID_ATTR *priv); - NTSTATUS (*get_sid_privileges) (DOM_SID **privs, const DOM_SID *sid); - /* warning!: set_privilege will overwrite a prior existing privilege if such exist */ - NTSTATUS (*set_privilege) (GUMS_PRIVILEGE *priv); - - -int gumm_init(GUMS_FUNCTIONS **storage) -{ - tdbsam2_db = NULL; - teo_handlers = 0; - - return 0; -} - -#if 0 -int main(int argc, char *argv[]) -{ - NTSTATUS ret; - DOM_SID dsid; - - if (argc < 2) { - printf ("not enough arguments!\n"); - exit(0); - } - - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); - exit(1); - } - - ret = tdbsam2_new_object(&dsid, "_domain_", GUMS_OBJ_DOMAIN); - if (NT_STATUS_IS_OK(ret)) { - printf ("_domain_ created, sid=%s\n", sid_string_static(&dsid)); - } else { - printf ("_domain_ creation error n. 0x%08x\n", ret.v); - } - ret = tdbsam2_new_object(&dsid, argv[1], GUMS_OBJ_NORMAL_USER); - if (NT_STATUS_IS_OK(ret)) { - printf ("%s user created, sid=%s\n", argv[1], sid_string_static(&dsid)); - } else { - printf ("%s user creation error n. 0x%08x\n", argv[1], ret.v); - } - - exit(0); -} -#endif diff --git a/source3/sam/gums_tdbsam2.c b/source3/sam/gums_tdbsam2.c new file mode 100644 index 0000000000..82e3923f7c --- /dev/null +++ b/source3/sam/gums_tdbsam2.c @@ -0,0 +1,1297 @@ +/* + * Unix SMB/CIFS implementation. + * tdbsam2 - sam backend + * Copyright (C) Simo Sorce 2002-2003 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "tdbsam2.h" +#include "tdbsam2_parse_info.h" + +static int gums_tdbsam2_debug_class = DBGC_ALL; +/* +#undef DBGC_CLASS +#define DBGC_CLASS gums_tdbsam2_debug_class +*/ + +#define TDBSAM_VERSION 20021215 +#define TDB_FILE_NAME "tdbsam2.tdb" +#define NAMEPREFIX "NAME_" +#define SIDPREFIX "SID_" +#define PRIVILEGEPREFIX "PRIV_" + +#define TDB_FORMAT_STRING "ddB" + +#define TALLOC_CHECK(ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: Out of memory!\n", FUNCTION_MACRO)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) +#define SET_OR_FAIL(func, label) do { if (!NT_STATUS_IS_OK(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0) + + + +struct tdbsam2_enum_objs { + uint32 type; + DOM_SID *dom_sid; + TDB_CONTEXT *db; + TDB_DATA key; + struct tdbsam2_enum_objs *next; +}; + +union tdbsam2_data { + struct tdbsam2_domain_data *domain; + struct tdbsam2_user_data *user; + struct tdbsam2_group_data *group; + struct tdbsam2_priv_data *priv; +}; + +struct tdbsam2_object { + uint32 type; + uint32 version; + union tdbsam2_data data; +}; + +struct tdbsam2_private_data { + + const char *storage; + struct tdbsam2_enum_objs *teo_handlers; +}; + +static struct tdbsam2_private_data *ts2_privs; + + +static NTSTATUS init_object_from_buffer(GUMS_OBJECT **go, char *buffer, int size) +{ + + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *mem_ctx; + int iret; + char *obj_data = NULL; + int data_size = 0; + int version, type; + int len; + + mem_ctx = talloc_init("init_object_from_buffer"); + if (!mem_ctx) { + DEBUG(0, ("init_object_from_buffer: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + len = tdb_unpack (buffer, size, TDB_FORMAT_STRING, + &version, + &type, + &data_size, &obj_data); + + if (len == -1 || data_size <= 0) + goto done; + + /* version is checked inside this function so that backward compatibility code can be + called eventually. + this way we can easily handle database format upgrades */ + if (version != TDBSAM_VERSION) { + DEBUG(3,("init_tdbsam2_object_from_buffer: Error, db object has wrong tdbsam version!\n")); + goto done; + } + + /* be sure the string is terminated before trying to parse it */ + if (obj_data[data_size - 1] != '\0') + obj_data[data_size - 1] = '\0'; + + *go = (GUMS_OBJECT *)talloc_zero(mem_ctx, sizeof(GUMS_OBJECT)); + TALLOC_CHECK(*go, ret, done); + + switch (type) { + + case GUMS_OBJ_DOMAIN: + iret = gen_parse(mem_ctx, pinfo_tdbsam2_domain_data, (char *)(*go), obj_data); + break; + + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + iret = gen_parse(mem_ctx, pinfo_tdbsam2_group_data, (char *)(*go), obj_data); + break; + + case GUMS_OBJ_NORMAL_USER: + iret = gen_parse(mem_ctx, pinfo_tdbsam2_user_data, (char *)(*go), obj_data); + break; + + case GUMS_OBJ_PRIVILEGE: + iret = gen_parse(mem_ctx, pinfo_tdbsam2_priv_data, (char *)(*go), obj_data); + break; + + default: + DEBUG(3,("init_object_from_buffer: Error, wrong object type number!\n")); + goto done; + } + + if (iret != 0) { + DEBUG(0, ("init_object_from_buffer: Fatal Error! Unable to parse object!\n")); + DEBUG(0, ("init_object_from_buffer: DB Corrupt ?")); + goto done; + } + + (*go)->mem_ctx = mem_ctx; + + ret = NT_STATUS_OK; +done: + SAFE_FREE(obj_data); + return ret; +} + +static NTSTATUS init_buffer_from_object(char **buffer, size_t *len, TALLOC_CTX *mem_ctx, GUMS_OBJECT *object) +{ + + NTSTATUS ret; + char *genbuf = NULL; + size_t buflen; + + if (!buffer) + return NT_STATUS_INVALID_PARAMETER; + + switch (gums_get_object_type(object)) { + + case GUMS_OBJ_DOMAIN: + genbuf = gen_dump(mem_ctx, pinfo_tdbsam2_domain_data, (char *)object, 0); + break; + + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + genbuf = gen_dump(mem_ctx, pinfo_tdbsam2_group_data, (char *)object, 0); + break; + + case GUMS_OBJ_NORMAL_USER: + genbuf = gen_dump(mem_ctx, pinfo_tdbsam2_user_data, (char *)object, 0); + break; + + case GUMS_OBJ_PRIVILEGE: + genbuf = gen_dump(mem_ctx, pinfo_tdbsam2_priv_data, (char *)object, 0); + break; + + default: + DEBUG(3,("init_buffer_from_object: Error, wrong object type number!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (genbuf == NULL) { + DEBUG(0, ("init_buffer_from_object: Fatal Error! Unable to dump object!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + buflen = tdb_pack(NULL, 0, TDB_FORMAT_STRING, + TDBSAM_VERSION, + object->type, + strlen(genbuf) + 1, genbuf); + + *buffer = talloc(mem_ctx, buflen); + TALLOC_CHECK(*buffer, ret, done); + + *len = tdb_pack(*buffer, buflen, TDB_FORMAT_STRING, + TDBSAM_VERSION, + object->type, + strlen(genbuf) + 1, genbuf); + + if (*len != buflen) { + DEBUG(0, ("init_buffer_from_object: something odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", + buflen, *len)); + *buffer = NULL; + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ret = NT_STATUS_OK; +done: + return ret; +} + +static NTSTATUS opentdb(TDB_CONTEXT **tdb, BOOL readonly) +{ + if (!tdb) + return NT_STATUS_INVALID_PARAMETER; + + *tdb = tdb_open_log(ts2_privs->storage, 0, TDB_DEFAULT, readonly?(O_RDONLY):(O_RDWR | O_CREAT), 0600); + if (!(*tdb)) + { + DEBUG(0, ("opentdb: Unable to open database (%s)!\n", ts2_privs->storage)); + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + +static NTSTATUS get_object_by_sid(TDB_CONTEXT *tdb, GUMS_OBJECT **obj, const DOM_SID *sid) +{ + NTSTATUS ret; + TDB_DATA data, key; + fstring keystr; + + if (!obj || !sid) + return NT_STATUS_INVALID_PARAMETER; + + slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid)); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(tdb, key); + if (!data.dptr) { + DEBUG(5, ("get_object_by_sid: Entry not found!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); + ret = NT_STATUS_NOT_FOUND; + goto done; + } + + if (!NT_STATUS_IS_OK(init_object_from_buffer(obj, data.dptr, data.dsize))) { + DEBUG(0, ("get_object_by_sid: Error fetching database, malformed entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ret = NT_STATUS_OK; + +done: + SAFE_FREE(data.dptr); + return ret; +} + +static NTSTATUS get_object_by_name(TDB_CONTEXT *tdb, GUMS_OBJECT **obj, const char* name) +{ + + NTSTATUS ret = NT_STATUS_OK; + TDB_DATA data, key; + fstring keystr; + fstring objname; + DOM_SID sid; + fstring sidstr; + int sidstr_len; + + if (!obj || !name) + return NT_STATUS_INVALID_PARAMETER; + + /* Data is stored in all lower-case */ + fstrcpy(objname, name); + strlower_m(objname); + + slprintf(keystr, sizeof(keystr)-1, "%s%s", NAMEPREFIX, objname); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(tdb, key); + if (!data.dptr) { + DEBUG(5, ("get_object_by_name: Entry not found!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); + ret = NT_STATUS_NOT_FOUND; + goto done; + } + + fstrcpy(sidstr, data.dptr); + sidstr_len = data.dsize; + + SAFE_FREE(data.dptr); + + if (sidstr_len <= 0) { + DEBUG(5, ("get_object_by_name: Error unpacking database object!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!string_to_sid(&sid, sidstr)) { + DEBUG(5, ("get_object_by_name: Error invalid sid string found in database object!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + +done: + if (NT_STATUS_IS_OK(ret)) + return get_object_by_sid(tdb, obj, &sid); + return ret; +} + +/* store a tdbsam2_object + * flag: TDB_REPLACE or TDB_MODIFY or TDB_INSERT + */ + +static NTSTATUS store_object(TDB_CONTEXT *tdb, const GUMS_OBJECT *object, int flag) +{ + + NTSTATUS ret = NT_STATUS_OK; + TDB_DATA data, data2, key, key2; + TALLOC_CTX *mem_ctx; + fstring keystr; + fstring sidstr; + fstring namestr; + fstring objname; + int r; + + /* TODO: on object renaming/replacing this function should + * check name->sid record and delete the old one + */ + + mem_ctx = talloc_init("store_object"); + if (!mem_ctx) { + DEBUG(0, ("store_object: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (!NT_STATUS_IS_OK(ret = init_buffer_from_object(&(data.dptr), &(data.dsize), mem_ctx, object))) + goto done; + + switch (object->type) { + + case GUMS_OBJ_DOMAIN: + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + case GUMS_OBJ_NORMAL_USER: + + fstrcpy(sidstr, sid_string_static(gums_get_object_sid(object))); + slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sidstr); + break; + + default: + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Data is stored in all lower-case */ + fstrcpy(objname, gums_get_object_name(object)); + strlower_m(objname); + + slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, objname); + + if (object->type != GUMS_OBJ_PRIVILEGE) { + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + if ((r = tdb_store(tdb, key, data, flag)) != TDB_SUCCESS) { + DEBUG(0, ("store_object: Unable to modify TDBSAM!\n")); + DEBUGADD(0, (" Error: %s", tdb_errorstr(tdb))); + DEBUGADD(0, (" occured while storing sid record (%s)\n", keystr)); + if (r == TDB_ERR_EXISTS) + ret = NT_STATUS_UNSUCCESSFUL; + else + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + data2.dptr = sidstr; + data2.dsize = strlen(sidstr) + 1; + key2.dptr = namestr; + key2.dsize = strlen(namestr) + 1; + + if ((r = tdb_store(tdb, key2, data2, flag)) != TDB_SUCCESS) { + DEBUG(0, ("store_object: Unable to modify TDBSAM!\n")); + DEBUGADD(0, (" Error: %s", tdb_errorstr(tdb))); + DEBUGADD(0, (" occured while storing name record (%s)\n", keystr)); + DEBUGADD(0, (" attempting rollback operation.\n")); + if ((tdb_delete(tdb, key)) != TDB_SUCCESS) { + DEBUG(0, ("store_object: Unable to rollback! Check database consitency!\n")); + } + if (r == TDB_ERR_EXISTS) + ret = NT_STATUS_UNSUCCESSFUL; + else + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + } else { + key.dptr = namestr; + key.dsize = strlen(keystr) + 1; + + if ((r = tdb_store(tdb, key, data, flag)) != TDB_SUCCESS) { + DEBUG(0, ("store_object: Unable to modify TDBSAM!\n")); + DEBUGADD(0, (" Error: %s", tdb_errorstr(tdb))); + DEBUGADD(0, (" occured while storing sid record (%s)\n", keystr)); + if (r == TDB_ERR_EXISTS) + ret = NT_STATUS_UNSUCCESSFUL; + else + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + } + +/* TODO: update the general database counter */ +/* TODO: update this entry counter too */ + +done: + talloc_destroy(mem_ctx); + return ret; +} + +#if 0 +static NTSTATUS user_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_user_data *userdata) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + DATA_BLOB pwd; + + if (!object || !userdata) { + DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL pointers are accepted here!\n")); + return ret; + } + + /* userdata->xcounter */ + /* userdata->sec_desc */ + + SET_OR_FAIL(gums_set_object_sid(*object, userdata->user_sid), error); + SET_OR_FAIL(gums_set_object_name(*object, userdata->name), error); + + SET_OR_FAIL(gums_set_user_pri_group(*object, userdata->group_sid), error); + + if (userdata->description) + SET_OR_FAIL(gums_set_object_description(*object, userdata->description), error); + + if (userdata->full_name) + SET_OR_FAIL(gums_set_user_fullname(*object, userdata->full_name), error); + + if (userdata->home_dir) + SET_OR_FAIL(gums_set_user_homedir(*object, userdata->home_dir), error); + + if (userdata->dir_drive) + SET_OR_FAIL(gums_set_user_dir_drive(*object, userdata->dir_drive), error); + + if (userdata->logon_script) + SET_OR_FAIL(gums_set_user_logon_script(*object, userdata->logon_script), error); + + if (userdata->profile_path) + SET_OR_FAIL(gums_set_user_profile_path(*object, userdata->profile_path), error); + + if (userdata->workstations) + SET_OR_FAIL(gums_set_user_workstations(*object, userdata->workstations), error); + + if (userdata->unknown_str) + SET_OR_FAIL(gums_set_user_unknown_str(*object, userdata->unknown_str), error); + + if (userdata->munged_dial) + SET_OR_FAIL(gums_set_user_munged_dial(*object, userdata->munged_dial), error); + + SET_OR_FAIL(gums_set_user_logon_divs(*object, userdata->logon_divs), error); + + if (userdata->hours) + SET_OR_FAIL(gums_set_user_hours(*object, userdata->hours_len, userdata->hours), error); + + SET_OR_FAIL(gums_set_user_unknown_3(*object, userdata->unknown_3), error); + SET_OR_FAIL(gums_set_user_unknown_5(*object, userdata->unknown_5), error); + SET_OR_FAIL(gums_set_user_unknown_6(*object, userdata->unknown_6), error); + + SET_OR_FAIL(gums_set_user_logon_time(*object, *(userdata->logon_time)), error); + SET_OR_FAIL(gums_set_user_logoff_time(*object, *(userdata->logoff_time)), error); + SET_OR_FAIL(gums_set_user_kickoff_time(*object, *(userdata->kickoff_time)), error); + SET_OR_FAIL(gums_set_user_pass_last_set_time(*object, *(userdata->pass_last_set_time)), error); + SET_OR_FAIL(gums_set_user_pass_can_change_time(*object, *(userdata->pass_can_change_time)), error); + SET_OR_FAIL(gums_set_user_pass_must_change_time(*object, *(userdata->pass_must_change_time)), error); + + pwd = data_blob(userdata->nt_pw_ptr, NT_HASH_LEN); + ret = gums_set_user_nt_pwd(*object, pwd); + data_blob_clear_free(&pwd); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(5, ("user_data_to_gums_object: failed to set nt password!\n")); + goto error; + } + pwd = data_blob(userdata->lm_pw_ptr, LM_HASH_LEN); + ret = gums_set_user_lm_pwd(*object, pwd); + data_blob_clear_free(&pwd); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(5, ("user_data_to_gums_object: failed to set lanman password!\n")); + goto error; + } + + ret = NT_STATUS_OK; + return ret; + +error: + talloc_destroy((*object)->mem_ctx); + *object = NULL; + return ret; +} + +static NTSTATUS group_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_group_data *groupdata) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!object || !groupdata) { + DEBUG(0, ("tdbsam2_group_data_to_gums_object: no NULL pointers are accepted here!\n")); + return ret; + } + + /* groupdata->xcounter */ + /* groupdata->sec_desc */ + + SET_OR_FAIL(gums_set_object_sid(*object, groupdata->group_sid), error); + SET_OR_FAIL(gums_set_object_name(*object, groupdata->name), error); + + if (groupdata->description) + SET_OR_FAIL(gums_set_object_description(*object, groupdata->description), error); + + if (groupdata->count) + SET_OR_FAIL(gums_set_group_members(*object, groupdata->count, groupdata->members), error); + + ret = NT_STATUS_OK; + return ret; + +error: + talloc_destroy((*object)->mem_ctx); + *object = NULL; + return ret; +} + +static NTSTATUS domain_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_domain_data *domdata) +{ + + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!object || !*object || !domdata) { + DEBUG(0, ("tdbsam2_domain_data_to_gums_object: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + /* domdata->xcounter */ + /* domdata->sec_desc */ + + SET_OR_FAIL(gums_set_object_sid(*object, domdata->dom_sid), error); + SET_OR_FAIL(gums_set_object_name(*object, domdata->name), error); + + if (domdata->description) + SET_OR_FAIL(gums_set_object_description(*object, domdata->description), error); + + ret = NT_STATUS_OK; + return ret; + +error: + talloc_destroy((*object)->mem_ctx); + *object = NULL; + return ret; +} + +static NTSTATUS priv_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_priv_data *privdata) +{ + + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!object || !*object || !privdata) { + DEBUG(0, ("tdbsam2_priv_data_to_gums_object: no NULL pointers are accepted here!\n")); + return ret; + } + + /* domdata->xcounter */ + /* domdata->sec_desc */ + + SET_OR_FAIL(gums_set_priv_luid_attr(*object, privdata->privilege), error); + SET_OR_FAIL(gums_set_object_name(*object, privdata->name), error); + + if (privdata->description) + SET_OR_FAIL(gums_set_object_description(*object, privdata->description), error); + + if (privdata->count) + SET_OR_FAIL(gums_set_priv_members(*object, privdata->count, privdata->members), error); + + ret = NT_STATUS_OK; + return ret; + +error: + talloc_destroy((*object)->mem_ctx); + *object = NULL; + return ret; +} + +static NTSTATUS data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_object *data) +{ + + NTSTATUS ret; + + if (!object || !data) { + DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL structure pointers are accepted here!\n")); + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + ret = gums_create_object(object, data->type); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(5, ("tdbsam2_user_data_to_gums_object: error creating gums object!\n")); + goto done; + } + + switch (data->type) { + + case GUMS_OBJ_DOMAIN: + ret = domain_data_to_gums_object(object, data->data.domain); + break; + + case GUMS_OBJ_NORMAL_USER: + ret = user_data_to_gums_object(object, data->data.user); + break; + + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + ret = group_data_to_gums_object(object, data->data.group); + break; + + case GUMS_OBJ_PRIVILEGE: + ret = priv_data_to_gums_object(object, data->data.priv); + break; + + default: + ret = NT_STATUS_UNSUCCESSFUL; + } + +done: + return ret; +} +#endif + +/* GUMM object functions */ + +static NTSTATUS tdbsam2_get_domain_sid(DOM_SID *sid, const char* name) +{ + + NTSTATUS ret; + TDB_CONTEXT *tdb; + GUMS_OBJECT *go; + fstring domname; + + if (!sid || !name) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, True))) { + return ret; + } + + /* Data is stored in all lower-case */ + fstrcpy(domname, name); + strlower_m(domname); + + if (!NT_STATUS_IS_OK(ret = get_object_by_name(tdb, &go, domname))) { + go = NULL; + DEBUG(0, ("tdbsam2_get_domain_sid: Error fetching database!\n")); + goto done; + } + + if (gums_get_object_type(go) != GUMS_OBJ_DOMAIN) { + DEBUG(5, ("tdbsam2_get_domain_sid: Requested object is not a domain!\n")); + ret = NT_STATUS_OBJECT_TYPE_MISMATCH; + goto done; + } + + sid_copy(sid, gums_get_object_sid(go)); + + ret = NT_STATUS_OK; + +done: + if (go) + gums_destroy_object(&go); + tdb_close(tdb); + return ret; +} + +static NTSTATUS get_next_sid(TDB_CONTEXT *tdb, DOM_SID *sid) +{ + NTSTATUS ret; + GUMS_OBJECT *go; + DOM_SID dom_sid; + TDB_DATA dom_sid_key; + fstring dom_sid_str; + uint32 new_rid; + + /* Find the domain SID */ + if (!NT_STATUS_IS_OK(tdbsam2_get_domain_sid(&dom_sid, global_myname()))) { + DEBUG(0, ("get_next_sid: cannot found the domain sid!!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Lock the domain record */ + sid_to_string(dom_sid_str, &dom_sid); + dom_sid_key.dptr = dom_sid_str; + dom_sid_key.dsize = strlen(dom_sid_key.dptr) + 1; + + if(tdb_chainlock(tdb, dom_sid_key) != 0) { + DEBUG(0, ("get_next_sid: unable to lock domain record!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Get the domain object */ + ret = get_object_by_sid(tdb, &go, &dom_sid); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("get_next_sid: unable to get root Domain object!\n")); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + new_rid = gums_get_domain_next_rid(go); + + /* Increment the RID Counter */ + gums_set_domain_next_rid(go, new_rid+1); + + /* Store back Domain object */ + ret = store_object(tdb, go, TDB_MODIFY); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("get_next_sid: unable to update root Domain object!\n")); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + /* Build the Domain SID to return */ + sid_copy(sid, &dom_sid); + + if (!sid_append_rid(sid, new_rid)) { + DEBUG(0, ("get_next_sid: unable to build new SID !?!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ret = NT_STATUS_OK; + +done: + /* Unlock the Domain object */ + tdb_chainunlock(tdb, dom_sid_key); + + return ret; +} + +/* TODO */ + NTSTATUS (*get_sequence_number) (void); + + +extern DOM_SID global_sid_NULL; + +static NTSTATUS tdbsam2_new_object(DOM_SID *sid, const char *name, const int obj_type) +{ + + NTSTATUS ret = NT_STATUS_OK; + TDB_CONTEXT *tdb; + GUMS_OBJECT *go; + NTTIME null_time; + DATA_BLOB pw; + const char *defpw = "NOPASSWORDXXXXXX"; + uint8 defhours[21] = {255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; + + if (!name) { + DEBUG(0, ("tdbsam2_new_object: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, False))) { + return ret; + } + + if (!NT_STATUS_IS_OK(ret = gums_create_object(&go, obj_type))) { + go = NULL; + goto done; + } + + if (obj_type != GUMS_OBJ_PRIVILEGE) { + if (!sid) { + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (obj_type == GUMS_OBJ_DOMAIN) { + sid_copy(sid, get_global_sam_sid()); + } else { + if (!NT_STATUS_IS_OK(ret = get_next_sid(tdb, sid))) + goto done; + } + + gums_set_object_sid(go, sid); + } + + gums_set_object_name(go, name); + gums_set_object_seq_num(go, 1); + + /*obj.data.domain->sec_desc*/ + + switch (obj_type) { + case GUMS_OBJ_NORMAL_USER: + + init_nt_time(&null_time); + + gums_set_user_logon_time(go, null_time); + gums_set_user_logoff_time(go, null_time); + gums_set_user_kickoff_time(go, null_time); + gums_set_user_pass_last_set_time(go, null_time); + gums_set_user_pass_can_change_time(go, null_time); + gums_set_user_pass_must_change_time(go, null_time); + + pw = data_blob(defpw, NT_HASH_LEN); + gums_set_user_nt_pwd(go, pw); + gums_set_user_lm_pwd(go, pw); + data_blob_free(&pw); + + gums_set_user_logon_divs(go, 168); + gums_set_user_hours(go, 21, defhours); + + gums_set_user_unknown_3(go, 0x00ffffff); + gums_set_user_bad_password_count(go, 0); + gums_set_user_logon_count(go, 0); + gums_set_user_unknown_6(go, 0x000004ec); + break; + + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + + break; + + case GUMS_OBJ_DOMAIN: + + gums_set_domain_next_rid(go, 0x3e9); + + break; + + case GUMS_OBJ_PRIVILEGE: + + break; + + default: + ret = NT_STATUS_OBJECT_TYPE_MISMATCH; + goto done; + } + + ret = store_object(tdb, go, TDB_INSERT); + +done: + if (go) + gums_destroy_object(&go); + tdb_close(tdb); + return ret; +} + +static NTSTATUS tdbsam2_delete_object(const DOM_SID *sid) +{ + /* TODO: need to address privilege deletion */ + NTSTATUS ret = NT_STATUS_OK; + TDB_CONTEXT *tdb; + GUMS_OBJECT *go; + TDB_DATA data, key; + fstring keystr; + + if (!sid) { + DEBUG(0, ("tdbsam2_delete_object: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, False))) { + return ret; + } + + slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid)); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(tdb, key); + if (!data.dptr) { + DEBUG(5, ("tdbsam2_delete_object: Error fetching database, SID entry not found!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (tdb_delete(tdb, key) != TDB_SUCCESS) { + DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!NT_STATUS_IS_OK(init_object_from_buffer(&go, data.dptr, data.dsize))) { + DEBUG(0, ("tdbsam2_delete_object: Error fetching database, malformed entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + switch (go->type) { + case GUMS_OBJ_DOMAIN: + /* FIXME: SHOULD WE ALLOW TO DELETE DOMAINS ? */ + case GUMS_OBJ_GROUP: + case GUMS_OBJ_ALIAS: + case GUMS_OBJ_NORMAL_USER: + slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, gums_get_object_name(go)); + break; + default: + ret = NT_STATUS_OBJECT_TYPE_MISMATCH; + goto done; + } + + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + if (tdb_delete(tdb, key) != TDB_SUCCESS) { + DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + +/* TODO: update the general database counter */ + +done: + gums_destroy_object(&go); + SAFE_FREE(data.dptr); + return ret; +} + +static NTSTATUS tdbsam2_get_object_from_sid(GUMS_OBJECT **object, const DOM_SID *sid, const int obj_type) +{ + NTSTATUS ret; + TDB_CONTEXT *tdb; + + if (!object || !sid) { + DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, True))) { + return ret; + } + + ret = get_object_by_sid(tdb, object, sid); + if (!NT_STATUS_IS_OK(ret) || (obj_type && gums_get_object_type(*object) != obj_type)) { + DEBUG(0, ("tdbsam2_get_object_from_sid: %s\n", nt_errstr(ret))); + goto error; + } + + tdb_close(tdb); + return NT_STATUS_OK; + +error: + gums_destroy_object(object); + tdb_close(tdb); + return ret; +} + +static NTSTATUS tdbsam2_get_object_from_name(GUMS_OBJECT **object, const char *name, const int obj_type) +{ + NTSTATUS ret; + TDB_CONTEXT *tdb; + + if (!object || !name) { + DEBUG(0, ("tdbsam2_get_object_from_name: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, True))) { + return ret; + } + + *object = NULL; + ret = get_object_by_name(tdb, object, name); + if (!NT_STATUS_IS_OK(ret) || (obj_type && gums_get_object_type(*object) != obj_type)) { + DEBUG(0, ("tdbsam2_get_object_from_name: %s\n", nt_errstr(ret))); + goto error; + } + + tdb_close(tdb); + return NT_STATUS_OK; + +error: + gums_destroy_object(object); + tdb_close(tdb); + return ret; +} + + /* This function is used to get the list of all objects changed since base_time, it is + used to support PDC<->BDC synchronization */ + NTSTATUS (*get_updated_objects) (GUMS_OBJECT **objects, const NTTIME base_time); + +static NTSTATUS tdbsam2_enumerate_objects_start(void **handle, const DOM_SID *sid, const int obj_type) +{ + struct tdbsam2_enum_objs *teo, *t; + + teo = (struct tdbsam2_enum_objs *)malloc(sizeof(struct tdbsam2_enum_objs)); + if (!teo) { + DEBUG(0, ("tdbsam2_enumerate_objects_start: Out of Memory!\n")); + return NT_STATUS_NO_MEMORY; + } + memset(teo, 0, sizeof(struct tdbsam2_enum_objs)); + + teo->type = obj_type; + if (sid) { + teo->dom_sid = (DOM_SID *)malloc(sizeof(DOM_SID)); + if (!teo->dom_sid) { + DEBUG(0, ("tdbsam2_enumerate_objects_start: Out of Memory!\n")); + return NT_STATUS_NO_MEMORY; + } + sid_copy(teo->dom_sid, sid); + } + + if (!NT_STATUS_IS_OK(opentdb(&(teo->db), True))) + { + DEBUG(0, ("tdbsam2_enumerate_objects_start: Unable to open database (%s)!\n", ts2_privs->storage)); + SAFE_FREE(teo); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!ts2_privs->teo_handlers) { + ts2_privs->teo_handlers = teo; + } else { + t = ts2_privs->teo_handlers; + while (t->next) { + t = t->next; + } + t->next = teo; + } + + *handle = teo; + + teo->key = tdb_firstkey(teo->db); + + return NT_STATUS_OK; +} + +static NTSTATUS tdbsam2_enumerate_objects_get_next(GUMS_OBJECT **object, void *handle) +{ + NTSTATUS ret; + TDB_DATA data; + struct tdbsam2_enum_objs *teo; + const char *prefix = SIDPREFIX; + const int preflen = strlen(prefix); + fstring dom_sid_str; + int dom_sid_str_len = 0; + + if (!object || !handle) { + DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + teo = (struct tdbsam2_enum_objs *)handle; + + if (teo->dom_sid) { + sid_to_string(dom_sid_str, teo->dom_sid); + dom_sid_str_len = strlen(dom_sid_str); + } + + while ((teo->key.dptr != NULL)) { + int len, version, type, size; + char *ptr; + + if (strncmp(teo->key.dptr, prefix, preflen)) { + teo->key = tdb_nextkey(teo->db, teo->key); + continue; + } + + if (dom_sid_str_len != 0) { + if (strncmp(&(teo->key.dptr[preflen]), dom_sid_str, dom_sid_str_len)) { + teo->key = tdb_nextkey(teo->db, teo->key); + continue; + } + } + + data = tdb_fetch(teo->db, teo->key); + if (!data.dptr) { + DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error fetching database, SID entry not found!\n")); + DEBUGADD(5, (" Error: %s\n", tdb_errorstr(teo->db))); + DEBUGADD(5, (" Key: %s\n", teo->key.dptr)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + len = tdb_unpack (data.dptr, data.dsize, TDB_FORMAT_STRING, + &version, + &type, + &size, &ptr); + + if (len == -1) { + DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error unable to unpack data!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + SAFE_FREE(ptr); + + if (teo->type && type != teo->type) { + SAFE_FREE(data.dptr); + data.dsize = 0; + teo->key = tdb_nextkey(teo->db, teo->key); + continue; + } + + break; + } + + if (teo->key.dptr == NULL) { /* no more objs */ + ret = NT_STATUS_NO_MORE_ENTRIES; + goto done; + } + + if (!NT_STATUS_IS_OK(ret = init_object_from_buffer(object, data.dptr, data.dsize))) { + SAFE_FREE(data.dptr); + DEBUG(0, ("tdbsam2_enumerate_objects_get_next: Error fetching database, malformed entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + SAFE_FREE(data.dptr); + + /* prepare next run */ + teo->key = tdb_nextkey(teo->db, teo->key); + +done: + return ret; +} + +static NTSTATUS tdbsam2_enumerate_objects_stop(void *handle) +{ + struct tdbsam2_enum_objs *teo, *t, *p; + + teo = (struct tdbsam2_enum_objs *)handle; + + if (ts2_privs->teo_handlers == teo) { + ts2_privs->teo_handlers = teo->next; + } else { + t = ts2_privs->teo_handlers; + while (t != teo) { + p = t; + t = t->next; + if (t == NULL) { + DEBUG(0, ("tdbsam2_enumerate_objects_stop: Error, handle not found!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + } + p = t->next; + } + + tdb_close(teo->db); + SAFE_FREE(teo->dom_sid); + SAFE_FREE(teo); + + return NT_STATUS_OK; +} + +static NTSTATUS tdbsam2_set_object(const GUMS_OBJECT *go) +{ + NTSTATUS ret; + TDB_CONTEXT *tdb; + + if (!go) + return NT_STATUS_INVALID_PARAMETER; + + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, False))) { + return ret; + } + + ret = store_object(tdb, go, TDB_REPLACE); + + tdb_close(tdb); + return ret; +} + + /* set object values function */ +static NTSTATUS (*set_object_values) (DOM_SID *sid, uint32 count, GUMS_DATA_SET *data_set); + + /* Group related functions */ +static NTSTATUS (*add_memberss_to_group) (const DOM_SID *group, const DOM_SID **members); + NTSTATUS (*delete_members_from_group) (const DOM_SID *group, const DOM_SID **members); +static NTSTATUS (*enumerate_group_members) (DOM_SID **members, const DOM_SID *sid, const int type); + +static NTSTATUS (*get_sid_groups) (DOM_SID **groups, const DOM_SID *sid); + +static NTSTATUS (*lock_sid) (const DOM_SID *sid); +static NTSTATUS (*unlock_sid) (const DOM_SID *sid); + + /* privileges related functions */ + +static NTSTATUS (*add_members_to_privilege) (const LUID_ATTR *priv, const DOM_SID **members); +static NTSTATUS (*delete_members_from_privilege) (const LUID_ATTR *priv, const DOM_SID **members); +static NTSTATUS (*enumerate_privilege_members) (DOM_SID **members, const LUID_ATTR *priv); +static NTSTATUS (*get_sid_privileges) (DOM_SID **privs, const DOM_SID *sid); + /* warning!: set_privilege will overwrite a prior existing privilege if such exist */ +static NTSTATUS (*set_privilege) (GUMS_PRIVILEGE *priv); + +static void free_tdbsam2_private_data(void **vp) +{ + struct tdbsam2_private_data **tdb_privs = (struct tdbsam2_private_data **)vp; + while (ts2_privs->teo_handlers) + tdbsam2_enumerate_objects_stop(ts2_privs->teo_handlers); + *tdb_privs = NULL; + /* No need to free any further, as it is talloc()ed */ +} + +static NTSTATUS init_tdbsam2(GUMS_FUNCTIONS *fns, const char *storage) +{ + NTSTATUS ret; + TDB_CONTEXT *tdb; + DOM_SID dom_sid; + + fns->name = talloc_strdup(fns->mem_ctx, "tdbsam2"); + + fns->get_domain_sid = tdbsam2_get_domain_sid; + /* fns->get_sequence_number = tdbsam2_get_sequence_number; */ + fns->new_object = tdbsam2_new_object; + fns->delete_object = tdbsam2_delete_object; + fns->get_object_from_sid = tdbsam2_get_object_from_sid; + fns->get_object_from_name = tdbsam2_get_object_from_name; + /* fns->get_updated_objects = tdbsam2_get_updated_objects; */ + fns->enumerate_objects_start = tdbsam2_enumerate_objects_start; + fns->enumerate_objects_get_next = tdbsam2_enumerate_objects_get_next; + fns->enumerate_objects_stop = tdbsam2_enumerate_objects_stop; + fns->set_object = tdbsam2_set_object; + /* fns->set_object_values = tdbsam2_set_object_values; + fns->add_members_to_group = tdbsam2_add_members_to_group; + fns->delete_members_from_group = tdbsam2_delete_members_from_group; + fns->enumerate_group_members = tdbsam2_enumerate_group_members; + fns->get_sid_groups = tdbsam2_get_sid_groups; + fns->lock_sid = tdbsam2_lock_sid; + fns->unlock_sid = tdbsam2_unlock_sid; + fns->add_members_to_privilege = tdbsam2_add_members_to_privilege; + fns->delete_members_from_privilege = tdbsam2_delete_members_from_privilege; + fns->enumerate_privilege_members = tdbsam2_enumerate_privilege_members; + fns->get_sid_privileges = tdbsam2_get_sid_privileges; + fns->set_privilege = tdbsam2_set_privilege; */ + + ts2_privs = talloc_zero(fns->mem_ctx, sizeof(struct tdbsam2_private_data)); + if (!ts2_privs) { + DEBUG(0, ("talloc() failed for tdbsam2 private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (storage) { + ts2_privs->storage = talloc_strdup(fns->mem_ctx, storage); + } else { + pstring tdbfile; + get_private_directory(tdbfile); + pstrcat(tdbfile, "/"); + pstrcat(tdbfile, TDB_FILE_NAME); + ts2_privs->storage = talloc_strdup(fns->mem_ctx, tdbfile); + } + + /* check tdb exist (or create it) */ + + /* Find the domain SID */ + if (!NT_STATUS_IS_OK(tdbsam2_get_domain_sid(&dom_sid, global_myname()))) { + /* db file does not exist or it is not inited */ + /* make the tdb file */ + if (!NT_STATUS_IS_OK(ret = opentdb(&tdb, False))) { + return ret; + } + tdb_close(tdb); + + if (!NT_STATUS_IS_OK(tdbsam2_get_domain_sid(&dom_sid, "BUILTIN"))) { + gums_init_builtin_domain(); + } + + gums_init_domain(get_global_sam_sid(), global_myname()); + } + + fns->private_data = &ts2_privs; + fns->free_private_data = free_tdbsam2_private_data; + + return NT_STATUS_OK; +} + +NTSTATUS gums_tdbsam2_init(void) +{ + /* + if ((gums_tdbsam2_debug_class = debug_add_class("gums_tdbsam2")) == -1) { + DEBUG(0, ("gums_tdbsam2: unable to register my own debug class! going on ...\n")); + gums_tdbsam2_debug_class = DBGC_ALL; + } + */ + return gums_register_module(GUMS_INTERFACE_VERSION, "tdbsam2", init_tdbsam2); +} -- cgit From eaed556ebada5dbcbe2d25cf5297e408c8d7a27c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Oct 2003 07:50:36 +0000 Subject: fix typo (This used to be commit 2d46b2a0e7de21158003968b630ebcd40bde7e44) --- source3/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index a0dd6de2f9..f3b3f9272b 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -4104,7 +4104,7 @@ SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB) SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB) SMB_MODULE(pdb_gums, passdb/pdb_gums.o, "bin/gums.$SHLIBEXT", PDB) -SMB_SUBSYSTEM(PDB,passdb/pdb_interface.c) +SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o) SMB_MODULE(gums_tdbsam2, sam/gums_tdbsam2.o, "bin/tdbsam2.$SHLIBEXT", GUMS) SMB_SUBSYSTEM(GUMS) -- cgit From 613974ffd8d1d6db444cabcd3a8e16f055959236 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Oct 2003 17:02:09 +0000 Subject: Enable us to see what sequence number we were expecting when we fail a sign (should help track down out of sequence bugs). Jeremy. (This used to be commit c6a36d4e486bf1aa384adf7db37878e485476216) --- source3/libsmb/smb_signing.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 08ff655a3f..8a4401ef19 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -385,8 +385,8 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) for (i = 0; i < 10; i++, reply_seq_number++) { simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { - DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches.\n", - reply_seq_number )); + DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \ +We were expecting seq %u\n", reply_seq_number, saved_seq )); break; } } @@ -748,8 +748,8 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) for (i = 0; i < 10; i++, reply_seq_number++) { simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { - DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches.\n", - reply_seq_number )); + DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \ +We were expecting seq %u\n", reply_seq_number, saved_seq )); break; } } -- cgit From eecd346f1d6864df99f615e163370d48d5b48ef1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 14 Oct 2003 22:41:30 +0000 Subject: updating version in copyright (This used to be commit 63ff13b2093aed43468c0ff2a49db7f22cffe587) --- source3/printing/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/printing/notify.c b/source3/printing/notify.c index e2146d5018..f2dd7d4f22 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -1,6 +1,6 @@ /* Unix SMB/Netbios implementation. - Version 2.2 + Version 3.0 printing backend routines Copyright (C) Tim Potter, 2002 Copyright (C) Gerald Carter, 2002 -- cgit From 311d739eb761e8a90777e20fd545a00965393eb4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 15 Oct 2003 17:41:25 +0000 Subject: created a new target: genparse this target will build parse file with genstruct it is the duty of the developer to commit updated files this is made to make build platforms independent of a working perl installation as always been with samba so currently you need to run: make genparse and commit: cvs ci include/tdbsam2_parse_info.h if you change anything in genparse/genstruct code or tdbsam2 code. Simo. (This used to be commit 7e2d5da2dcfad32b733c28535490e98e578bcc3a) --- source3/Makefile.in | 11 +++++++---- source3/include/.cvsignore | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index e377c7a85e..8cd2c9f621 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1308,15 +1308,14 @@ clean: delheaders python_clean # afterwards. proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ - client/client_proto.h utils/net_proto.h smbd/build_options.c \ - include/tdbsam2_parse_info.h + client/client_proto.h utils/net_proto.h smbd/build_options.c delheaders: @echo Removing prototype headers @rm -f include/proto.h include/build_env.h include/wrepld_proto.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ client/client_proto.h utils/net_proto.h \ - smbd/build_options.c include/tdbsam2_parse_info.h + smbd/build_options.c MKPROTO_SH = $(srcdir)/script/mkproto.sh @@ -1378,9 +1377,13 @@ headers: $(MAKE) nsswitch/winbindd_proto.h; \ $(MAKE) web/swat_proto.h; \ $(MAKE) client/client_proto.h; \ - $(MAKE) utils/net_proto.h; \ + $(MAKE) utils/net_proto.h; + +prebuiltheaders: $(MAKE) include/tdbsam2_parse_info.h +genparse: prebuiltheaders + proto: headers .PHONY: headers proto diff --git a/source3/include/.cvsignore b/source3/include/.cvsignore index 6f72267aaa..3827fdf70d 100644 --- a/source3/include/.cvsignore +++ b/source3/include/.cvsignore @@ -3,6 +3,5 @@ config.h config.h.in proto.h stamp-h -tdbsam2_parse_info.h version.h wrepld_proto.h -- cgit From 21d53cbbaef23bce63ff4deebf9273ac036e7979 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 00:45:14 +0000 Subject: Ensure error code path doesn't free unmalloced memory. Bug #628. Jeremy. (This used to be commit ef183bf00f5bad9f9c898067b48ebe052beddc82) --- source3/smbd/lanman.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b27ccc23ef..30934d0b3a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -522,6 +522,8 @@ static void fill_printq_info_52(connection_struct *conn, int snum, NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; + ZERO_STRUCT(driver); + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", lp_servicename(snum))); @@ -679,6 +681,8 @@ static int get_printerdrivernumber(int snum) NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; + ZERO_STRUCT(driver); + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", lp_servicename(snum))); -- cgit From eafd0371402009db8051d04b1ae988e8f8817031 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 18:17:41 +0000 Subject: Fix buggy data_len calculation in echo. Add paranoia debug message. Jeremy. (This used to be commit 8fb05cfa3afd9777c161271c4c3cec0d6d5150f2) --- source3/smbd/reply.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec63be32b4..011186ba89 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2784,7 +2784,11 @@ int reply_echo(connection_struct *conn, int outsize = set_message(outbuf,1,data_len,True); START_PROFILE(SMBecho); - data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf))); + if (data_len > BUFFER_SIZE) { + DEBUG(0,("reply_echo: data_len too large.\n")); + END_PROFILE(SMBecho); + return -1; + } /* copy any incoming data back out */ if (data_len > 0) -- cgit From cdd02fa792c460b6022738d23e64ff4e3526ec11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 20:44:41 +0000 Subject: Tidyup wrap checking. Jeremy. (This used to be commit 707554bcce91f33d0931f9d99050aab50765f5ff) --- source3/smbd/ipc.c | 20 ++++++++++++++------ source3/smbd/nttrans.c | 16 ++++++++++++---- source3/smbd/trans2.c | 16 ++++++++++++---- 3 files changed, 38 insertions(+), 14 deletions(-) (limited to 'source3') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 39072f9b91..9bdd02b059 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -388,7 +388,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - if (smb_base(inbuf)+dsoff+dscnt > inbuf + size) + if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || + (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) goto bad_param; memcpy(data,smb_base(inbuf)+dsoff,dscnt); @@ -402,8 +403,9 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) - goto bad_param; - if (smb_base(inbuf)+psoff+pscnt > inbuf + size) + goto bad_param; + if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))); goto bad_param; memcpy(params,smb_base(inbuf)+psoff,pscnt); @@ -487,8 +489,11 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (pdisp+pcnt >= tpscnt) goto bad_param; if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) + goto bad_param; + if (pdisp > tpscnt) + goto bad_param; + if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) || + (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) goto bad_param; if (params + pdisp < params) goto bad_param; @@ -501,7 +506,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) goto bad_param; - if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) + if (ddisp > tdscnt) + goto bad_param; + if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) || + (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) goto bad_param; if (data + ddisp < data) goto bad_param; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b4e7a70088..19af61f190 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2463,7 +2463,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((parameter_offset + parameter_count < parameter_offset) || (parameter_offset + parameter_count < parameter_count)) goto bad_param; - if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) + if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)|| + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); @@ -2473,7 +2474,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) goto bad_param; - if (smb_base(inbuf) + data_offset + data_count > inbuf + length) + if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; memcpy( data, smb_base(inbuf) + data_offset, data_count); @@ -2534,7 +2536,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((parameter_displacement + parameter_count < parameter_displacement) || (parameter_displacement + parameter_count < parameter_count)) goto bad_param; - if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) + if (parameter_displacement > total_parameter_count) + goto bad_param; + if ((smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) || + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; if (parameter_displacement + params < params) goto bad_param; @@ -2548,7 +2553,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((data_displacement + data_count < data_displacement) || (data_displacement + data_count < data_count)) goto bad_param; - if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) + if (data_displacement > total_data_count) + goto bad_param; + if ((smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) || + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; if (data_displacement + data < data) goto bad_param; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3d53387c9f..0f02403184 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3497,7 +3497,8 @@ int reply_trans2(connection_struct *conn, unsigned int psoff = SVAL(inbuf, smb_psoff); if ((psoff + num_params < psoff) || (psoff + num_params < num_params)) goto bad_param; - if (smb_base(inbuf) + psoff + num_params > inbuf + length) + if ((smb_base(inbuf) + psoff + num_params > inbuf + length) || + (smb_base(inbuf) + psoff + num_params < smb_base(inbuf))) goto bad_param; memcpy( params, smb_base(inbuf) + psoff, num_params); } @@ -3505,7 +3506,8 @@ int reply_trans2(connection_struct *conn, unsigned int dsoff = SVAL(inbuf, smb_dsoff); if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data)) goto bad_param; - if (smb_base(inbuf) + dsoff + num_data > inbuf + length) + if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) || + (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf))) goto bad_param; memcpy( data, smb_base(inbuf) + dsoff, num_data); } @@ -3566,7 +3568,10 @@ int reply_trans2(connection_struct *conn, if ((param_disp + num_params < param_disp) || (param_disp + num_params < num_params)) goto bad_param; - if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) + if (param_disp > total_params) + goto bad_param; + if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) || + (smb_base(inbuf) + param_off + num_params < smb_base(inbuf))) goto bad_param; if (params + param_disp < params) goto bad_param; @@ -3579,7 +3584,10 @@ int reply_trans2(connection_struct *conn, if ((data_disp + num_data < data_disp) || (data_disp + num_data < num_data)) goto bad_param; - if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) + if (data_disp > total_data) + goto bad_param; + if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) || + (smb_base(inbuf) + data_off + num_data < smb_base(inbuf))) goto bad_param; if (data + data_disp < data) goto bad_param; -- cgit From 440e7e476e59713f43f11480dfd78569cfdb3e99 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Thu, 16 Oct 2003 22:03:34 +0000 Subject: Remove DEBUG statement from wb_common.c as it should not be there. (This used to be commit 51f12170affd87cdff23118ed16f85dd97914f0c) --- source3/nsswitch/wb_common.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3') diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 6c47d149f0..f146391653 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -191,8 +191,6 @@ static int winbind_named_pipe_sock(const char *dir) if (connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { - DEBUG(10, ("error connecting to pipe socket: %s\n", - strerror(errno))); close(fd); return -1; } -- cgit From 6b5f7e70d727d927fd8537cd4fce29f9154be088 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 17 Oct 2003 15:02:38 +0000 Subject: Add endpoint mapper rpc definitions (This used to be commit e604a9c0788a006663e7f939059c4120c1df3648) --- source3/include/rpc_epmapper.h | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 source3/include/rpc_epmapper.h (limited to 'source3') diff --git a/source3/include/rpc_epmapper.h b/source3/include/rpc_epmapper.h new file mode 100644 index 0000000000..57ac8e2522 --- /dev/null +++ b/source3/include/rpc_epmapper.h @@ -0,0 +1,115 @@ +/* + Unix SMB/CIFS implementation. + Endpoint mapper data definitions + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define EPM_HANDLE_LEN 20 + +/* ordinal for the mapping interface */ + +#define EPM_MAP_PIPE_NAME 0x03 + +/* some of the different connection protocols and their IDs from Windows */ + +#define EPM_FLOOR_UUID 0x0d /* floor contains UUID */ +#define EPM_FLOOR_RPC 0x0b /* tower is for connection-oriented rpc */ +#define EPM_FLOOR_TCP 0x07 /* floor contains tcp port number */ +#define EPM_FLOOR_IP 0x09 /* floor contains IP address */ +#define EPM_FLOOR_NMPIPES 0x10 /* floor contains remote named pipe name */ +#define EPM_FLOOR_NETBIOS 0x11 /* floor contains netbios address */ +#define EPM_FLOOR_NETBEUI 0x12 /* floor contains netbeui address */ +#define EPM_FLOOR_SOCKET 0x20 + +#define EPM_PIPE_NM "epmapper" + +#define MAX_TOWERS 1 + +typedef struct +{ + uint8 data[EPM_HANDLE_LEN]; +} EPM_HANDLE; + +typedef struct +{ + struct { + uint16 length; + uint8 protocol; + struct { + RPC_UUID uuid; + uint16 version; + } uuid; + } lhs; + struct { + uint16 length; + uint16 unknown; + struct { + uint16 port; + } tcp; + struct { + uint8 addr[4]; + } ip; + } rhs; +} EPM_FLOOR; + +typedef struct +{ + uint32 referent_id; + uint32 max_length; + uint32 length; + uint16 num_floors; + EPM_FLOOR *floors; + uint8 unknown; +} EPM_TOWER; + +typedef struct +{ + EPM_HANDLE handle; + EPM_TOWER *tower; + EPM_HANDLE term_handle; /* in/out */ + uint32 max_towers; +} EPM_Q_MAP; + +typedef struct +{ + uint32 max_count; + uint32 offset; + uint32 count; + EPM_TOWER *towers; +} EPM_TOWER_ARRAY; + +typedef struct +{ + EPM_HANDLE handle; + uint32 num_results; + EPM_TOWER_ARRAY *results; + uint32 status; +} EPM_R_MAP; + + +/* port mapping entries to be read */ + +typedef struct _mapper_entries{ + uint8 protocol ; + RPC_IFACE uuid_info ; /* needs to be zeroed if no specific uuid */ + uint16 port ; + char pipe_name[40] ; + char srv_name[20] ; + uint8 srv_port[4] ; + char func_name[16][16]; /* array of up to 16 functions available */ +} mapper_entries; + -- cgit From a6ff6254dad51acfc484c0ef92c1c484d466f509 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 17 Oct 2003 15:03:46 +0000 Subject: Add (un)marshalling code for endpoint mapper map operation (This used to be commit bdd5158d9a45f4b935ea0fa495c0d83bc5ca96f8) --- source3/rpc_parse/parse_epmapper.c | 406 +++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 source3/rpc_parse/parse_epmapper.c (limited to 'source3') diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c new file mode 100644 index 0000000000..9e21da04dd --- /dev/null +++ b/source3/rpc_parse/parse_epmapper.c @@ -0,0 +1,406 @@ +/* + Unix SMB/CIFS implementation. + Samba end point mapper functions + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* + Reads or writes a handle. +********************************************************************/ +BOOL epm_io_handle(const char *desc, EPM_HANDLE *handle, prs_struct *ps, + int depth) +{ + + if (!prs_uint8s(False, "data", ps, depth, handle->data, + sizeof(handle->data))) + return False; + + return True; +} + +/******************************************************************* + inits an EPM_FLOOR structure. +********************************************************************/ +NTSTATUS init_epm_floor(EPM_FLOOR *floor, uint8 protocol) +{ + /* handle lhs */ + floor->lhs.protocol = protocol; + floor->lhs.length = sizeof(floor->lhs.protocol); + + switch(floor->lhs.protocol) { + case EPM_FLOOR_UUID: + floor->lhs.length += sizeof(floor->lhs.uuid.uuid); + floor->lhs.length += sizeof(floor->lhs.uuid.version); + break; + default: + break; + } + + /* handle rhs */ + switch(floor->lhs.protocol) { + case EPM_FLOOR_RPC: + case EPM_FLOOR_UUID: + floor->rhs.length = sizeof(floor->rhs.unknown); + break; + case EPM_FLOOR_TCP: + floor->rhs.length = sizeof(floor->rhs.tcp.port); + break; + case EPM_FLOOR_IP: + floor->rhs.length = sizeof(floor->rhs.ip.addr); + break; + default: + break; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + inits an EPM_FLOOR structure with a UUID +********************************************************************/ +NTSTATUS init_epm_floor_uuid(EPM_FLOOR *floor, + const RPC_UUID *uuid, uint16 version) +{ + memcpy(&floor->lhs.uuid.uuid, uuid, sizeof(*uuid)); + floor->lhs.uuid.version = version; + floor->rhs.unknown = 0; + return init_epm_floor(floor, EPM_FLOOR_UUID); +} + +/******************************************************************* + inits an EPM_FLOOR structure for RPC +********************************************************************/ +NTSTATUS init_epm_floor_rpc(EPM_FLOOR *floor) +{ + floor->rhs.unknown = 0; + return init_epm_floor(floor, EPM_FLOOR_RPC); +} + +/******************************************************************* + inits an EPM_FLOOR structure for TCP +********************************************************************/ +NTSTATUS init_epm_floor_tcp(EPM_FLOOR *floor, uint16 port) +{ + floor->rhs.tcp.port = htons(port); + return init_epm_floor(floor, EPM_FLOOR_TCP); +} + +/******************************************************************* + inits an EPM_FLOOR structure for IP +********************************************************************/ +NTSTATUS init_epm_floor_ip(EPM_FLOOR *floor, uint8 addr[4]) +{ + memcpy(&floor->rhs.ip.addr, addr, sizeof(addr)); + return init_epm_floor(floor, EPM_FLOOR_IP); +} + +/******************************************************************* + reads and writes EPM_FLOOR. +********************************************************************/ +BOOL epm_io_floor(const char *desc, EPM_FLOOR *floor, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "epm_io_floor"); + depth++; + + if (!prs_uint16("lhs_length", ps, depth, &floor->lhs.length)) + return False; + if (!prs_uint8("protocol", ps, depth, &floor->lhs.protocol)) + return False; + + switch (floor->lhs.protocol) { + case EPM_FLOOR_UUID: + if (!smb_io_rpc_uuid("uuid", &floor->lhs.uuid.uuid, ps, depth)) + return False; + if (!prs_uint16("version", ps, depth, + &floor->lhs.uuid.version)) + return False; + break; + } + + if (!prs_uint16("rhs_length", ps, depth, &floor->rhs.length)) + return False; + + switch (floor->lhs.protocol) { + case EPM_FLOOR_UUID: + case EPM_FLOOR_RPC: + if (!prs_uint16("unknown", ps, depth, &floor->rhs.unknown)) + return False; + break; + case EPM_FLOOR_TCP: + if (!prs_uint16("tcp_port", ps, depth, &floor->rhs.tcp.port)) + return False; + break; + case EPM_FLOOR_IP: + if (!prs_uint8s(False, "ip_addr", ps, depth, + floor->rhs.ip.addr, + sizeof(floor->rhs.ip.addr))) + return False; + break; + default: + break; + } + + return True; +} + +/******************************************************************* + Inits a EPM_TOWER structure. +********************************************************************/ +NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, + const EPM_FLOOR *floors, int num_floors) +{ + static uint32 internal_referent_id = 0; + int size = 0; + int i; + + DEBUG(5, ("init_epm_tower\n")); + + for (i = 0; i < num_floors; i++) { + size += (sizeof(uint32) * 2); + size += floors[i].lhs.length; + size += floors[i].rhs.length; + } + size += sizeof(uint8); /* this could be aligning... */ + + tower->referent_id = ++internal_referent_id; + tower->max_length = tower->length = size; + tower->num_floors = num_floors; + tower->floors = talloc(ctx, sizeof(EPM_FLOOR) * num_floors); + if (!tower->floors) { + return NT_STATUS_NO_MEMORY; + } + memcpy(tower->floors, floors, sizeof(EPM_FLOOR) * num_floors); + tower->unknown = 0x7e; + + return NT_STATUS_OK; +} + +/******************************************************************* + Reads or writes an EPM_TOWER structure. +********************************************************************/ +BOOL epm_io_tower(const char *desc, EPM_TOWER *tower, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_tower"); + depth++; + + if (!prs_uint32("referent_id", ps, depth, &tower->referent_id)) + return False; + if (!prs_uint32("max_length", ps, depth, &tower->max_length)) + return False; + if (!prs_uint32("length", ps, depth, &tower->length)) + return False; + if (!prs_uint16("num_floors", ps, depth, &tower->num_floors)) + return False; + + if (UNMARSHALLING(ps)) { + tower->floors = talloc(ps->mem_ctx, + sizeof(EPM_FLOOR) * tower->num_floors); + if (!tower->floors) + return False; + } + + for (i = 0; i < tower->num_floors; i++) { + if (!epm_io_floor("floor", tower->floors + i, ps, depth)) + return False; + } + + if (!prs_uint8("unknown", ps, depth, &tower->unknown)) + return False; + + return True; +} + +/******************************************************************* + Initialize an EPM_TOWER_ARRAY structure +********************************************************************/ +NTSTATUS init_epm_tower_array(TALLOC_CTX *ctx, EPM_TOWER_ARRAY *array, + const EPM_TOWER *towers, int num_towers) +{ + array->max_count = num_towers; + array->offset = 0; + array->count = num_towers; + array->towers = talloc(ctx, sizeof(EPM_TOWER) * num_towers); + if (!array->towers) { + return NT_STATUS_NO_MEMORY; + } + memcpy(array->towers, towers, sizeof(EPM_TOWER) * num_towers); + + return NT_STATUS_OK; +} + +/******************************************************************* + Reads or writes an EPM_TOWER_ARRAY structure. +********************************************************************/ +BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_tower_array"); + depth++; + + if (!prs_uint32("max_count", ps, depth, &array->max_count)) + return False; + if (!prs_uint32("offset", ps, depth, &array->offset)) + return False; + if (!prs_uint32("count", ps, depth, &array->count)) + return False; + + if (!prs_set_offset(ps, prs_offset(ps) + array->offset)) + return False; + + if (UNMARSHALLING(ps)) { + array->towers = talloc(ps->mem_ctx, + sizeof(EPM_TOWER) * array->count); + if (!array->towers) { + return False; + } + } + + for (i = 0; i < array->count; i++) { + if (!epm_io_tower("tower", array->towers + 1, ps, depth)) + return False; + } + + return True; +} + +/******************************************************************* + Initialize EPM_R_MAP structure +******************************************************************/ +NTSTATUS init_epm_r_map(TALLOC_CTX *ctx, EPM_R_MAP *r_map, + const EPM_HANDLE *handle, const EPM_TOWER_ARRAY *array, + int num_elements, uint32 status) +{ + memcpy(&r_map->handle, handle, sizeof(*handle)); + r_map->num_results = num_elements; + r_map->results = talloc(ctx, sizeof(EPM_TOWER_ARRAY) * num_elements); + if (!r_map->results) { + return NT_STATUS_NO_MEMORY; + } + memcpy(r_map->results, array, sizeof(EPM_TOWER_ARRAY) * num_elements); + r_map->status = status; + return NT_STATUS_OK; +} + +/************************************************************************* + Inits a EPM_Q_MAP structure. +************************************************************************** +* We attempt to hide the ugliness of the wire format by taking a EPM_TOWER +* array with a defined size +**************************************************************************/ +NTSTATUS init_epm_q_map(TALLOC_CTX *ctx, EPM_Q_MAP *q_map, + const EPM_TOWER *towers, int num_towers) +{ + static uint32 handle = 1; + + ZERO_STRUCTP(q_map); + + DEBUG(5, ("init_epm_q_map\n")); + q_map->handle.data[0] = (handle >> 0) & 0xFF; + q_map->handle.data[1] = (handle >> 8) & 0xFF; + q_map->handle.data[2] = (handle >> 16) & 0xFF; + q_map->handle.data[3] = (handle >> 24) & 0xFF; + + q_map->tower = talloc(ctx, sizeof(EPM_TOWER) * (num_towers + 1)); + if (!q_map->tower) { + return NT_STATUS_NO_MEMORY; + } + + memcpy(q_map->tower, towers, sizeof(EPM_TOWER) * num_towers); + + ZERO_STRUCT(q_map->tower[num_towers]); + + /* For now let's not take more than 4 towers per result */ + q_map->max_towers = num_towers * 4; + + handle++; + + return NT_STATUS_OK; +} + +/***************************************************************** + epm_io_q_map - read or write EPM_Q_MAP structure +******************************************************************/ +BOOL epm_io_q_map(char *desc, EPM_Q_MAP *io_map, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "epm_io_q_map"); + depth++; + + if (!epm_io_handle("handle", &io_map->handle, ps, depth)) + return False; + + /* HACK: We need a more elegant way of doing this */ + if (UNMARSHALLING(ps)) { + io_map->tower = talloc(ps->mem_ctx, sizeof(EPM_TOWER)); + if (!io_map->tower) + return False; + } + if (!epm_io_tower("tower", io_map->tower, ps, depth)) + return False; + if (!epm_io_handle("term_handle", &io_map->term_handle, ps, depth)) + return False; + + if (!prs_uint32("max_towers", ps, 0, &io_map->max_towers)) + return False; + + return True; +} + +/******************************************************************* + epm_io_r_map - Read/Write EPM_R_MAP structure +******************************************************************/ +BOOL epm_io_r_map(char *desc, EPM_R_MAP *io_map, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_r_map"); + depth++; + + if (!epm_io_handle("handle", &io_map->handle, ps, depth)) + return False; + if (!prs_uint32("num_results", ps, depth, &io_map->num_results)) + return False; + + if (UNMARSHALLING(ps)) { + io_map->results = talloc(ps->mem_ctx, + sizeof(EPM_TOWER_ARRAY) * + io_map->num_results); + if (!io_map->results) + return False; + } + for (i = 0; i < io_map->num_results; i++) { + if (!epm_io_tower_array("results", io_map->results + i, + ps, depth)) + return False; + } + + if (!prs_uint32("status", ps, depth, &io_map->status)) + return False; + + return True; +} -- cgit From d807bc12fb1d208de9b4f9e2532810cf1a9e3695 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 17 Oct 2003 15:07:23 +0000 Subject: Add epmapper pipe (This used to be commit 041c17bd665ea5fa771b111d7008036fb3e7b72f) --- source3/include/ntdomain.h | 1 + source3/include/smb.h | 4 +++- source3/rpc_parse/parse_rpc.c | 12 +++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index ccbc190c59..66057424ca 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -402,5 +402,6 @@ struct acct_info #include "rpc_dfs.h" #include "rpc_ds.h" #include "rpc_echo.h" +#include "rpc_epmapper.h" #endif /* _NT_DOMAIN_H */ diff --git a/source3/include/smb.h b/source3/include/smb.h index 8c6f47f23f..1e4c48132a 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -194,6 +194,7 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PIPE_SPOOLSS "\\PIPE\\spoolss" #define PIPE_NETDFS "\\PIPE\\netdfs" #define PIPE_ECHO "\\PIPE\\rpcecho" +#define PIPE_EPM "\\PIPE\\epmapper" #define PIPE_NETLOGON_PLAIN "\\NETLOGON" @@ -207,7 +208,8 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PI_SPOOLSS 7 #define PI_NETDFS 8 #define PI_ECHO 9 -#define PI_MAX_PIPES 10 +#define PI_EPM 10 +#define PI_MAX_PIPES 11 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ typedef struct nttime_info diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 1ea59feaed..57ebe5d356 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -147,6 +147,15 @@ interface/version dce/rpc pipe identification }, 0x01 \ } +#define SYNT_EPM_V3 \ +{ \ + { \ + 0xe1af8308, 0x5d1f, 0x11c9, \ + { 0x91, 0xa4, 0x08, 0x00, \ + 0x2b, 0x14, 0xa0, 0xfa } \ + }, 0x03 \ +} + /* * IMPORTANT!! If you update this structure, make sure to * update the index #defines in smb.h. @@ -165,6 +174,7 @@ const struct pipe_id_info pipe_names [] = { PIPE_SPOOLSS , SYNT_SPOOLSS_V1 , PIPE_SPOOLSS , TRANS_SYNT_V2 }, { PIPE_NETDFS , SYNT_NETDFS_V3 , PIPE_NETDFS , TRANS_SYNT_V2 }, { PIPE_ECHO , SYNT_ECHO_V1 , PIPE_ECHO , TRANS_SYNT_V2 }, + { PIPE_EPM , SYNT_EPM_V3 , PIPE_EPM , TRANS_SYNT_V2 }, { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } }; @@ -246,7 +256,7 @@ BOOL smb_io_rpc_hdr(const char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) Reads or writes an RPC_UUID structure. ********************************************************************/ -static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth) +BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth) { if (uuid == NULL) return False; -- cgit From a278f48c6a2fe7c43c9f3f53eecad5d20c47b89e Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 17 Oct 2003 15:07:53 +0000 Subject: Add endpoint mapper parse code (This used to be commit 5537ccf95ae8c8d737cbcf9e5575b80b6b7bac6f) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 8cd2c9f621..eb69f92902 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -275,7 +275,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ rpc_parse/parse_samr.o rpc_parse/parse_srv.o \ rpc_parse/parse_wks.o rpc_parse/parse_ds.o \ rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \ - rpc_parse/parse_echo.o \ + rpc_parse/parse_echo.o rpc_parse/parse_epmapper.o \ $(REGOBJS_OBJ) -- cgit From 1b259ab003430bc38234c893f2fbbfb30cc7afa0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 17 Oct 2003 16:27:26 +0000 Subject: * fix some compile warnings in the gums code * add server support for DsEnumerateDomainTrusts() (This used to be commit 06bacf6e3434db5bd09b48f84206441712e69a63) --- source3/passdb/pdb_gums.c | 2 ++ source3/rpc_server/srv_netlog.c | 37 ++++++++++++++++++++++++++++++++++++- source3/rpc_server/srv_netlog_nt.c | 14 ++++++++++++++ source3/sam/gums_helper.c | 2 -- 4 files changed, 52 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/passdb/pdb_gums.c b/source3/passdb/pdb_gums.c index dd6e682452..caf98e648a 100644 --- a/source3/passdb/pdb_gums.c +++ b/source3/passdb/pdb_gums.c @@ -286,6 +286,8 @@ static NTSTATUS gums_getsampwrid (struct pdb_methods *methods, sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); gums_getsampwsid(methods, account, &sid); + + return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c index 9c10d86379..0ef9b088a9 100644 --- a/source3/rpc_server/srv_netlog.c +++ b/source3/rpc_server/srv_netlog.c @@ -317,6 +317,40 @@ static BOOL api_net_logon_ctrl(pipes_struct *p) return True; } +/************************************************************************* + api_ds_enum_dom_trusts: + *************************************************************************/ + +static BOOL api_ds_enum_dom_trusts(pipes_struct *p) +{ + DS_Q_ENUM_DOM_TRUSTS q_u; + DS_R_ENUM_DOM_TRUSTS r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + DEBUG(6,("api_ds_enum_dom_trusts\n")); + + if ( !ds_io_q_enum_domain_trusts("", data, 0, &q_u) ) { + DEBUG(0,("api_ds_enum_domain_trusts: Failed to unmarshall DS_Q_ENUM_DOM_TRUSTS.\n")); + return False; + } + + r_u.status = _ds_enum_dom_trusts(p, &q_u, &r_u); + + if ( !ds_io_r_enum_domain_trusts("", rdata, 0, &r_u) ) { + DEBUG(0,("api_ds_enum_domain_trusts: Failed to marshall DS_R_ENUM_DOM_TRUSTS.\n")); + return False; + } + + DEBUG(6,("api_ds_enum_dom_trusts\n")); + + return True; +} + /******************************************************************* array of \PIPE\NETLOGON operations ********************************************************************/ @@ -330,7 +364,8 @@ static struct api_struct api_net_cmds [] = { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff }, { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 }, { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list }, - { "NET_LOGON_CTRL" , NET_LOGON_CTRL , api_net_logon_ctrl } + { "NET_LOGON_CTRL" , NET_LOGON_CTRL , api_net_logon_ctrl }, + { "DS_ENUM_DOM_TRUSTS", DS_ENUM_DOM_TRUSTS, api_ds_enum_dom_trusts } }; void netlog_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 602cd7d2d5..66fa6e7678 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -762,4 +762,18 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * return status; } +/************************************************************************* + _ds_enum_dom_trusts + *************************************************************************/ +NTSTATUS _ds_enum_dom_trusts(pipes_struct *p, DS_Q_ENUM_DOM_TRUSTS *q_u, + DS_R_ENUM_DOM_TRUSTS *r_u) +{ + NTSTATUS status = NT_STATUS_OK; + /* We just return zero trusts for now. At least that way we're + consistent with NetTrustedDomainList which is what the fallback + for this function is. Both of these functions need to be + reworked. */ + + return status; +} diff --git a/source3/sam/gums_helper.c b/source3/sam/gums_helper.c index 15486d094c..5bbd054be1 100644 --- a/source3/sam/gums_helper.c +++ b/source3/sam/gums_helper.c @@ -173,7 +173,6 @@ NTSTATUS gums_make_domain(DOM_SID *sid, const char *name, const char *descriptio ret = fns->set_object(go); -done: gums_destroy_object(&go); return ret; } @@ -208,7 +207,6 @@ NTSTATUS gums_make_alias(DOM_SID *sid, const char *name, const char *description ret = fns->set_object(go); -done: gums_destroy_object(&go); return ret; } -- cgit From e6900132ca7d216662e3ab08ad37a1e34c752cd9 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 17 Oct 2003 19:47:06 +0000 Subject: uuid itself might not be aligned (as is the case in epm map requests), so it needs to be aligned outside the smb_io_rpc_uuid() call if a specific rpc or struct needs it that way. (This used to be commit e9fc15d58c52c12438c1f9c69394c11f76ce72d8) --- source3/rpc_parse/parse_rpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 57ebe5d356..f053297192 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -264,9 +264,6 @@ BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth prs_debug(ps, depth, desc, "smb_io_rpc_uuid"); depth++; - if(!prs_align(ps)) - return False; - if(!prs_uint32 ("data ", ps, depth, &uuid->time_low)) return False; if(!prs_uint16 ("data ", ps, depth, &uuid->time_mid)) @@ -292,6 +289,9 @@ static BOOL smb_io_rpc_iface(const char *desc, RPC_IFACE *ifc, prs_struct *ps, i prs_debug(ps, depth, desc, "smb_io_rpc_iface"); depth++; + if (!prs_align(ps)) + return False; + if (!smb_io_rpc_uuid( "uuid", &ifc->uuid, ps, depth)) return False; -- cgit From b227a561f7bae32353dc22aa78acf622f5c7fbe7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Oct 2003 21:19:17 +0000 Subject: Typo broke win9x logins. Jeremy. (This used to be commit a7afbce99830bffb8795e7dc2c80baeeba7dcd0a) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9bdd02b059..bc828d2e8e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -405,7 +405,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))); + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) goto bad_param; memcpy(params,smb_base(inbuf)+psoff,pscnt); -- cgit From ba0c899510e81eddfc76eeb1b3d875d5a8c6d0d0 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Sat, 18 Oct 2003 01:07:37 +0000 Subject: Fix tower length calculations and add some const (This used to be commit 2f84c6c9a1c292535e73721a8bcdb27aaa2b2b46) --- source3/rpc_parse/parse_epmapper.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c index 9e21da04dd..368ea319bd 100644 --- a/source3/rpc_parse/parse_epmapper.c +++ b/source3/rpc_parse/parse_epmapper.c @@ -175,12 +175,12 @@ NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, DEBUG(5, ("init_epm_tower\n")); + size += sizeof(uint16); /* number of floors is in tower length */ for (i = 0; i < num_floors; i++) { - size += (sizeof(uint32) * 2); + size += (sizeof(uint16) * 2); size += floors[i].lhs.length; size += floors[i].rhs.length; } - size += sizeof(uint8); /* this could be aligning... */ tower->referent_id = ++internal_referent_id; tower->max_length = tower->length = size; @@ -345,7 +345,8 @@ NTSTATUS init_epm_q_map(TALLOC_CTX *ctx, EPM_Q_MAP *q_map, /***************************************************************** epm_io_q_map - read or write EPM_Q_MAP structure ******************************************************************/ -BOOL epm_io_q_map(char *desc, EPM_Q_MAP *io_map, prs_struct *ps, int depth) +BOOL epm_io_q_map(const char *desc, EPM_Q_MAP *io_map, prs_struct *ps, + int depth) { prs_debug(ps, depth, desc, "epm_io_q_map"); depth++; @@ -373,7 +374,7 @@ BOOL epm_io_q_map(char *desc, EPM_Q_MAP *io_map, prs_struct *ps, int depth) /******************************************************************* epm_io_r_map - Read/Write EPM_R_MAP structure ******************************************************************/ -BOOL epm_io_r_map(char *desc, EPM_R_MAP *io_map, +BOOL epm_io_r_map(const char *desc, EPM_R_MAP *io_map, prs_struct *ps, int depth) { int i; -- cgit From 2702510b465b8ff562fabb73cbad6ca95fc8d955 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Sat, 18 Oct 2003 01:13:01 +0000 Subject: Add client side code to do endpoint map queries. Currently does one fixed query. Updates to come soon. (This used to be commit 3ca8240affba20bb26749354f59b83799b4f1e44) --- source3/rpc_client/cli_epmapper.c | 61 ++++++++++++++++++++++++++++++++++ source3/rpcclient/cmd_epmapper.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 source3/rpc_client/cli_epmapper.c create mode 100644 source3/rpcclient/cmd_epmapper.c (limited to 'source3') diff --git a/source3/rpc_client/cli_epmapper.c b/source3/rpc_client/cli_epmapper.c new file mode 100644 index 0000000000..66362f1620 --- /dev/null +++ b/source3/rpc_client/cli_epmapper.c @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +NTSTATUS cli_epm_map(struct cli_state *cli, TALLOC_CTX *mem_ctx, + EPM_HANDLE *handle, EPM_TOWER **tower, + EPM_HANDLE *entry_handle, uint32 *num_towers) +{ + prs_struct qbuf, rbuf; + EPM_Q_MAP q; + EPM_R_MAP r; + BOOL result = False; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_epm_q_map(mem_ctx, &q, *tower, *num_towers); + + if (!epm_io_q_map("map_query", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, EPM_MAP_PIPE_NAME, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!epm_io_r_map("map_reply", &r, &rbuf, 0)) + goto done; + + result = True; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; +} diff --git a/source3/rpcclient/cmd_epmapper.c b/source3/rpcclient/cmd_epmapper.c new file mode 100644 index 0000000000..280188d875 --- /dev/null +++ b/source3/rpcclient/cmd_epmapper.c @@ -0,0 +1,69 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "rpcclient.h" + + +static NTSTATUS cmd_epm_map(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + EPM_HANDLE handle, entry_handle; + EPM_TOWER *towers; + EPM_FLOOR floors[5]; + uint8 addr[4] = {0,0,0,0}; + uint32 numtowers; + /* need to allow all this stuff to be passed in, but + for now, it demonstrates the call */ + RPC_UUID if_uuid = {0xe3514235, 0x4b06, 0x11d1, \ + { 0xab, 0x04, 0x00, 0xc0, \ + 0x4f, 0xc2, 0xdc, 0xd2 }}, + syn_uuid = {0x8a885d04, 0x1ceb, 0x11c9, \ + { 0x9f, 0xe8, 0x08, 0x00, \ + 0x2b, 0x10, 0x48, 0x60 }}; + + NTSTATUS result; + + ZERO_STRUCT(handle); + numtowers = 1; + init_epm_floor_uuid(&floors[0], &if_uuid, 4); + init_epm_floor_uuid(&floors[1], &syn_uuid, 2); + init_epm_floor_rpc(&floors[2]); + init_epm_floor_tcp(&floors[3], 135); + init_epm_floor_ip(&floors[4], addr); + towers = talloc(mem_ctx, sizeof(EPM_TOWER)); + init_epm_tower(mem_ctx, towers, floors, 5); + + result = cli_epm_map(cli, mem_ctx, &handle, &towers, &entry_handle, &numtowers); + + return result; +} + +struct cmd_set epm_commands[] = { + + { "EPMAPPER" }, + + { "map", RPC_RTYPE_NTSTATUS, cmd_epm_map, NULL, PI_EPM, "map endpoint", "" }, + { NULL } +}; + + -- cgit From 18abf54675c4196d5cba3160216b8524efd04888 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Sat, 18 Oct 2003 01:14:25 +0000 Subject: Add epmapper client files to rpcclient build (This used to be commit 747501893c1d9b591c81a0e819f28d0102d596a5) --- source3/Makefile.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index eb69f92902..d8f8b4e526 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -234,7 +234,8 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \ rpc_client/cli_reg.o rpc_client/cli_pipe.o \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ - rpc_client/cli_ds.o rpc_client/cli_echo.o + rpc_client/cli_ds.o rpc_client/cli_echo.o \ + rpc_client/cli_epmapper.o REGOBJS_OBJ = registry/reg_objects.o REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ @@ -444,7 +445,7 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \ rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \ rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \ rpcclient/display_sec.o rpcclient/cmd_ds.o \ - rpcclient/cmd_echo.o + rpcclient/cmd_echo.o rpcclient/cmd_epmapper.o RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ -- cgit From 86102b0e1551a88911d8581279a1a578b577f2df Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Sat, 18 Oct 2003 01:14:41 +0000 Subject: Add epmapper commands to rpcclient (This used to be commit 1d68e108a744ae0e5df4d8d092a3b48fc4441ace) --- source3/rpcclient/rpcclient.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3') diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 773441a27c..f60cb67cba 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -462,6 +462,7 @@ extern struct cmd_set dfs_commands[]; extern struct cmd_set reg_commands[]; extern struct cmd_set ds_commands[]; extern struct cmd_set echo_commands[]; +extern struct cmd_set epm_commands[]; static struct cmd_set *rpcclient_command_list[] = { rpcclient_commands, @@ -474,6 +475,7 @@ static struct cmd_set *rpcclient_command_list[] = { dfs_commands, reg_commands, echo_commands, + epm_commands, NULL }; -- cgit From 2f643426731f473b7f77efa95c4898ca2233ccc1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 19 Oct 2003 23:30:09 +0000 Subject: Compile libsmbclient with DYNEXP (This used to be commit c8ec714119a620af3481e40a94c361704ecbc39b) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index d8f8b4e526..278d53be56 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -931,7 +931,7 @@ bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS) @echo Linking libsmbclient shared library $@ - @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR) -- cgit From 1db4a703a8aa1caf53da68a9dd085b6ff0a25505 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Oct 2003 14:02:58 +0000 Subject: make sure we have a devmode before copying a string to the devicename; patch from metze (This used to be commit 5479cb60c038969270353b9ff7a8e9967e066dfd) --- source3/printing/nt_printing.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 9c95cf9085..5b5b5885ab 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3306,10 +3306,11 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sh printername)); info.devmode = construct_nt_devicemode(printername); } - - safe_strcpy(adevice, info.printername, sizeof(adevice)-1); - fstrcpy(info.devmode->devicename, adevice); + safe_strcpy(adevice, info.printername, sizeof(adevice)-1); + if (info.devmode) { + fstrcpy(info.devmode->devicename, adevice); + } len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len ); -- cgit From bfcb776abd1ead323963912efef2641e0bc41a03 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Oct 2003 16:50:14 +0000 Subject: more 2.2.x compatibility fixes - allow user looksup in the kerb5 sesssetup to fall back to 'user' instaed of failing is REA.LM\user doesn't exist. also fix include line in smb_acls.h as requested by metze (This used to be commit 5ccf6baad7ffb1f992aaf24b41ef5c83362cf613) --- source3/auth/auth_util.c | 26 +++++++++++++++++++++++++- source3/include/smb_acls.h | 2 +- source3/smbd/sesssetup.c | 23 ++++++++++------------- 3 files changed, 36 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 3803741466..71634f08ed 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -942,7 +942,7 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, /* This is pointless -- there is no suport for differeing unix and windows names. Make sure to always store the - one we actuall looked up and succeeded. Have I mentioned + one we actually looked up and succeeded. Have I mentioned why I hate the 'winbind use default domain' parameter? --jerry */ @@ -951,6 +951,30 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, return pdb_init_sam_pw(sam_account, passwd); } +/**************************************************************************** + Wrapper to allow the getpwnam() call to styrip the domain name and + try again in case a local UNIX user is already there. + ****************************************************************************/ + +struct passwd *smb_getpwnam( char *domuser ) +{ + struct passwd *pw; + char *p; + + pw = Get_Pwnam( domuser ); + if ( pw ) + return pw; + + /* fallback to looking up just the username */ + + p = strchr( domuser, *lp_winbind_separator() ); + + if ( p ) + return Get_Pwnam(p+1); + + return NULL; +} + /*************************************************************************** Make a server_info struct from the info3 returned by a domain logon ***************************************************************************/ diff --git a/source3/include/smb_acls.h b/source3/include/smb_acls.h index e7edb62bde..2bde6caeda 100644 --- a/source3/include/smb_acls.h +++ b/source3/include/smb_acls.h @@ -195,7 +195,7 @@ typedef struct SMB_ACL_T { /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ -#include "/usr/include/acl.h" +#include typedef uint *SMB_ACL_PERMSET_T; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 427caa3ba1..945855b832 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -198,28 +198,25 @@ static int reply_spnego_kerberos(connection_struct *conn, /* this gives a fully qualified user name (ie. with full realm). that leads to very long usernames, but what else can we do? */ - asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client); + + asprintf(&user, "%s%c%s", p+1, *lp_winbind_separator(), client); - pw = Get_Pwnam(user); - if (!pw && !foreign) { - pw = Get_Pwnam(client); - SAFE_FREE(user); - user = smb_xstrdup(client); - } - + pw = smb_getpwnam( user ); + + SAFE_FREE(user); SAFE_FREE(client); - /* setup the string used by %U */ - sub_set_smb_name(user); - - reload_services(True); - if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + /* setup the string used by %U */ + + sub_set_smb_name(pw->pw_name); + reload_services(True); + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); data_blob_free(&ap_rep); -- cgit From f3121b19e4a4951350342a1882c9017686a995b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 2003 18:05:22 +0000 Subject: Merge tridge's tdb updates. Jeremy. (This used to be commit f81fdcc935317f66d562d485a40948c2a8bcbb21) --- source3/tdb/spinlock.c | 2 +- source3/tdb/spinlock.h | 4 ++++ source3/tdb/tdb.c | 6 ++++-- source3/tdb/tdbtorture.c | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/tdb/spinlock.c b/source3/tdb/spinlock.c index 2370ce3bdd..3fddeafb2c 100644 --- a/source3/tdb/spinlock.c +++ b/source3/tdb/spinlock.c @@ -372,7 +372,7 @@ int tdb_create_rwlocks(int fd, unsigned int hash_size) unsigned size, i; tdb_rwlock_t *rwlocks; - size = (hash_size + 1) * sizeof(tdb_rwlock_t); + size = TDB_SPINLOCK_SIZE(hash_size); rwlocks = malloc(size); if (!rwlocks) return -1; diff --git a/source3/tdb/spinlock.h b/source3/tdb/spinlock.h index 8b0e833ff5..967fe37457 100644 --- a/source3/tdb/spinlock.h +++ b/source3/tdb/spinlock.h @@ -39,6 +39,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_create_rwlocks(int fd, unsigned int hash_size); int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) + #else /* !USE_SPINLOCKS */ #if 0 #define tdb_create_rwlocks(fd, hash_size) 0 @@ -50,6 +52,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_create_rwlocks(int fd, unsigned int hash_size); #endif int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#define TDB_SPINLOCK_SIZE(hash_size) 0 + #endif #endif diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index f5809ef63a..e68bda4055 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -77,6 +77,8 @@ #define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) #define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) #define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) +#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) + /* NB assumes there is a local variable called "tdb" that is the * current context, also takes doubly-parenthesized print-style @@ -663,10 +665,10 @@ static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) left: /* Look left */ left = offset - sizeof(tdb_off); - if (left > TDB_HASH_TOP(tdb->header.hash_size-1)) { + if (left > TDB_DATA_START(tdb->header.hash_size)) { struct list_struct l; tdb_off leftsize; - + /* Read in tailer and jump back to header */ if (ofs_read(tdb, left, &leftsize) == -1) { TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); diff --git a/source3/tdb/tdbtorture.c b/source3/tdb/tdbtorture.c index e27bbff990..3f704e537e 100644 --- a/source3/tdb/tdbtorture.c +++ b/source3/tdb/tdbtorture.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include -- cgit From 2cfb3e9b7046fe2db330a292aed71f1c27688a16 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Mon, 20 Oct 2003 18:35:12 +0000 Subject: Several updates: - add support for named pipe and netbios queries in parse code - fix map request structure...unknown byte was alignment - add sample of named pipe over netbios query in rpcclient (comment only) (This used to be commit 71dcdf54e60204d6b499d25d8759ed20fc7a021a) --- source3/include/rpc_epmapper.h | 4 +++- source3/rpc_parse/parse_epmapper.c | 45 +++++++++++++++++++++++++++++++++++--- source3/rpcclient/cmd_epmapper.c | 5 +++++ 3 files changed, 50 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_epmapper.h b/source3/include/rpc_epmapper.h index 57ac8e2522..1b5b6b1876 100644 --- a/source3/include/rpc_epmapper.h +++ b/source3/include/rpc_epmapper.h @@ -30,7 +30,8 @@ #define EPM_FLOOR_RPC 0x0b /* tower is for connection-oriented rpc */ #define EPM_FLOOR_TCP 0x07 /* floor contains tcp port number */ #define EPM_FLOOR_IP 0x09 /* floor contains IP address */ -#define EPM_FLOOR_NMPIPES 0x10 /* floor contains remote named pipe name */ +#define EPM_FLOOR_NMPIPES 0x0f /* floor contains remote named pipe name */ +#define EPM_FLOOR_LRPC 0x10 /* floor contains local named pipe name */ #define EPM_FLOOR_NETBIOS 0x11 /* floor contains netbios address */ #define EPM_FLOOR_NETBEUI 0x12 /* floor contains netbeui address */ #define EPM_FLOOR_SOCKET 0x20 @@ -63,6 +64,7 @@ typedef struct struct { uint8 addr[4]; } ip; + char string[MAXHOSTNAMELEN+3]; /* hostname + \\ + null term */ } rhs; } EPM_FLOOR; diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c index 368ea319bd..2bdb755deb 100644 --- a/source3/rpc_parse/parse_epmapper.c +++ b/source3/rpc_parse/parse_epmapper.c @@ -29,6 +29,8 @@ BOOL epm_io_handle(const char *desc, EPM_HANDLE *handle, prs_struct *ps, int depth) { + if (!prs_align(ps)) + return False; if (!prs_uint8s(False, "data", ps, depth, handle->data, sizeof(handle->data))) @@ -67,6 +69,11 @@ NTSTATUS init_epm_floor(EPM_FLOOR *floor, uint8 protocol) case EPM_FLOOR_IP: floor->rhs.length = sizeof(floor->rhs.ip.addr); break; + case EPM_FLOOR_NMPIPES: + case EPM_FLOOR_LRPC: + case EPM_FLOOR_NETBIOS: + floor->rhs.length = strlen(floor->rhs.string) + 1; + break; default: break; } @@ -113,6 +120,33 @@ NTSTATUS init_epm_floor_ip(EPM_FLOOR *floor, uint8 addr[4]) return init_epm_floor(floor, EPM_FLOOR_IP); } +/******************************************************************* + inits an EPM_FLOOR structure for named pipe +********************************************************************/ +NTSTATUS init_epm_floor_np(EPM_FLOOR *floor, const char *pipe_name) +{ + safe_strcpy(floor->rhs.string, pipe_name, sizeof(floor->rhs.string)-1); + return init_epm_floor(floor, EPM_FLOOR_NMPIPES); +} + +/******************************************************************* + inits an EPM_FLOOR structure for named pipe +********************************************************************/ +NTSTATUS init_epm_floor_lrpc(EPM_FLOOR *floor, const char *pipe_name) +{ + safe_strcpy(floor->rhs.string, pipe_name, sizeof(floor->rhs.string)-1); + return init_epm_floor(floor, EPM_FLOOR_LRPC); +} + +/******************************************************************* + inits an EPM_FLOOR structure for named pipe +********************************************************************/ +NTSTATUS init_epm_floor_nb(EPM_FLOOR *floor, char *host_name) +{ + safe_strcpy(floor->rhs.string, host_name, sizeof(floor->rhs.string)-1); + return init_epm_floor(floor, EPM_FLOOR_NETBIOS); +} + /******************************************************************* reads and writes EPM_FLOOR. ********************************************************************/ @@ -156,6 +190,14 @@ BOOL epm_io_floor(const char *desc, EPM_FLOOR *floor, sizeof(floor->rhs.ip.addr))) return False; break; + case EPM_FLOOR_NMPIPES: + case EPM_FLOOR_LRPC: + case EPM_FLOOR_NETBIOS: + if (!prs_uint8s(False, "string", ps, depth, + floor->rhs.string, + floor->rhs.length)) + return False; + break; default: break; } @@ -227,9 +269,6 @@ BOOL epm_io_tower(const char *desc, EPM_TOWER *tower, return False; } - if (!prs_uint8("unknown", ps, depth, &tower->unknown)) - return False; - return True; } diff --git a/source3/rpcclient/cmd_epmapper.c b/source3/rpcclient/cmd_epmapper.c index 280188d875..e2eecb6f04 100644 --- a/source3/rpcclient/cmd_epmapper.c +++ b/source3/rpcclient/cmd_epmapper.c @@ -48,6 +48,11 @@ static NTSTATUS cmd_epm_map(struct cli_state *cli, init_epm_floor_uuid(&floors[0], &if_uuid, 4); init_epm_floor_uuid(&floors[1], &syn_uuid, 2); init_epm_floor_rpc(&floors[2]); + + /* sample for netbios named pipe query + init_epm_floor_np(&floors[3], "\\PIPE\\lsass"); + init_epm_floor_nb(&floors[4], "\\\\psflinux"); + */ init_epm_floor_tcp(&floors[3], 135); init_epm_floor_ip(&floors[4], addr); towers = talloc(mem_ctx, sizeof(EPM_TOWER)); -- cgit From 9d959807ff343107427589f36802b97583db79f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 2003 19:02:04 +0000 Subject: Merge Volker's fix. We are doing NT error codes now.... If we have an NT error, report that back the same way we handle the DOS error. Although I don't see why BUFFER_TOO_SMALL should not be handled as an error, simply copy the logic. This is only called from smbcacls and smbcquotas. Jeremy. (This used to be commit f67154fe41d7d458a11dfb9b2f0c6c26609c9a72) --- source3/libsmb/clitrans.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3') diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index e6771ac688..92c1cc99ee 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -488,6 +488,17 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, } } + /* + * Likewise for NT_STATUS_BUFFER_TOO_SMALL + */ + if (cli_is_nt_error(cli)) { + if (!NT_STATUS_EQUAL(cli_nt_error(cli), + NT_STATUS_BUFFER_TOO_SMALL)) { + cli_signing_trans_stop(cli); + return(False); + } + } + /* parse out the lengths */ total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount); total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount); -- cgit From 72569b4f1eb90d56a032e9d12fd97a5531a2467c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 2003 19:04:06 +0000 Subject: Merge Volker's fix. It's a perfectly valid condition to have zero alias members. Jeremy. (This used to be commit aa7fb71357921c9d1fa1d32e5eaff912428e4fdf) --- source3/rpc_client/cli_samr.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3') diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index f985ee9979..e5e67f39dc 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -865,6 +865,12 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, *num_mem = r.num_sids; + if (*num_mem == 0) { + *sids = NULL; + result = NT_STATUS_OK; + goto done; + } + if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) { result = NT_STATUS_UNSUCCESSFUL; goto done; -- cgit From 5fad0208ad386c35c2cb370d93808d3903d3fc8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 2003 21:02:05 +0000 Subject: Fixed typo spotted by Daniel Jarboe . Jeremy. (This used to be commit c68b6f64d9eb0808ce834e23174d1d6218b814b8) --- source3/rpcclient/cmd_spoolss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 05bfb2a0dc..eca31ae444 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -1246,7 +1246,7 @@ static BOOL init_drv_info_3_members ( } for (i=0; idependentfiles[i] = SSVAL(&info->dependentfiles[i], 0, str2[i]); + SSVAL(&info->dependentfiles[i], 0, str2[i]); } info->dependentfiles[len] = '\0'; -- cgit From 6fe9423fc69f3c1a79d0e45ac47d0b3228e4d4d6 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Mon, 20 Oct 2003 21:10:18 +0000 Subject: Update structures after ethereal showed some marshalling/unmarshalling errors. (This used to be commit 9d0f322a851f487cea320e57076213435e5c6481) --- source3/include/rpc_epmapper.h | 5 +++-- source3/rpc_parse/parse_epmapper.c | 44 ++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 11 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_epmapper.h b/source3/include/rpc_epmapper.h index 1b5b6b1876..de3a2cb08d 100644 --- a/source3/include/rpc_epmapper.h +++ b/source3/include/rpc_epmapper.h @@ -70,7 +70,6 @@ typedef struct typedef struct { - uint32 referent_id; uint32 max_length; uint32 length; uint16 num_floors; @@ -80,7 +79,8 @@ typedef struct typedef struct { - EPM_HANDLE handle; + EPM_HANDLE handle; + uint32 tower_ref_id; EPM_TOWER *tower; EPM_HANDLE term_handle; /* in/out */ uint32 max_towers; @@ -91,6 +91,7 @@ typedef struct uint32 max_count; uint32 offset; uint32 count; + uint32 *tower_ref_ids; EPM_TOWER *towers; } EPM_TOWER_ARRAY; diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c index 2bdb755deb..02340430ec 100644 --- a/source3/rpc_parse/parse_epmapper.c +++ b/source3/rpc_parse/parse_epmapper.c @@ -23,6 +23,9 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE +static uint32 internal_referent_id = 0; + + /******************************************************************* Reads or writes a handle. ********************************************************************/ @@ -211,7 +214,6 @@ BOOL epm_io_floor(const char *desc, EPM_FLOOR *floor, NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, const EPM_FLOOR *floors, int num_floors) { - static uint32 internal_referent_id = 0; int size = 0; int i; @@ -224,7 +226,6 @@ NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, size += floors[i].rhs.length; } - tower->referent_id = ++internal_referent_id; tower->max_length = tower->length = size; tower->num_floors = num_floors; tower->floors = talloc(ctx, sizeof(EPM_FLOOR) * num_floors); @@ -248,8 +249,9 @@ BOOL epm_io_tower(const char *desc, EPM_TOWER *tower, prs_debug(ps, depth, desc, "epm_io_tower"); depth++; - if (!prs_uint32("referent_id", ps, depth, &tower->referent_id)) + if (!prs_align(ps)) return False; + if (!prs_uint32("max_length", ps, depth, &tower->max_length)) return False; if (!prs_uint32("length", ps, depth, &tower->length)) @@ -278,9 +280,18 @@ BOOL epm_io_tower(const char *desc, EPM_TOWER *tower, NTSTATUS init_epm_tower_array(TALLOC_CTX *ctx, EPM_TOWER_ARRAY *array, const EPM_TOWER *towers, int num_towers) { + int i; + array->max_count = num_towers; array->offset = 0; array->count = num_towers; + array->tower_ref_ids = talloc(ctx, sizeof(uint32) * num_towers); + if (!array->tower_ref_ids) { + return NT_STATUS_NO_MEMORY; + } + for (i=0;itower_ref_ids[i] = ++internal_referent_id; + array->towers = talloc(ctx, sizeof(EPM_TOWER) * num_towers); if (!array->towers) { return NT_STATUS_NO_MEMORY; @@ -308,6 +319,18 @@ BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array, if (!prs_uint32("count", ps, depth, &array->count)) return False; + + if (UNMARSHALLING(ps)) { + array->tower_ref_ids = talloc(ps->mem_ctx, + sizeof(uint32) * array->count); + if (!array->tower_ref_ids) { + return False; + } + } + for (i=0; i < array->count; i++) + if (!prs_uint32("ref_id", ps, depth, &array->tower_ref_ids[i])) + return False; + if (!prs_set_offset(ps, prs_offset(ps) + array->offset)) return False; @@ -376,6 +399,8 @@ NTSTATUS init_epm_q_map(TALLOC_CTX *ctx, EPM_Q_MAP *q_map, /* For now let's not take more than 4 towers per result */ q_map->max_towers = num_towers * 4; + q_map->tower_ref_id = ++internal_referent_id; + handle++; return NT_STATUS_OK; @@ -393,6 +418,9 @@ BOOL epm_io_q_map(const char *desc, EPM_Q_MAP *io_map, prs_struct *ps, if (!epm_io_handle("handle", &io_map->handle, ps, depth)) return False; + if (!prs_uint32("max_towers", ps, 0, &io_map->tower_ref_id)) + return False; + /* HACK: We need a more elegant way of doing this */ if (UNMARSHALLING(ps)) { io_map->tower = talloc(ps->mem_ctx, sizeof(EPM_TOWER)); @@ -416,8 +444,6 @@ BOOL epm_io_q_map(const char *desc, EPM_Q_MAP *io_map, prs_struct *ps, BOOL epm_io_r_map(const char *desc, EPM_R_MAP *io_map, prs_struct *ps, int depth) { - int i; - prs_debug(ps, depth, desc, "epm_io_r_map"); depth++; @@ -433,11 +459,11 @@ BOOL epm_io_r_map(const char *desc, EPM_R_MAP *io_map, if (!io_map->results) return False; } - for (i = 0; i < io_map->num_results; i++) { - if (!epm_io_tower_array("results", io_map->results + i, - ps, depth)) + if (!epm_io_tower_array("results", io_map->results, ps, depth)) return False; - } + + if (!prs_align(ps)) + return False; if (!prs_uint32("status", ps, depth, &io_map->status)) return False; -- cgit From 043be81ec79ca5b4939577146a93813250cac96e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 21 Oct 2003 04:43:48 +0000 Subject: Merge of wrepld link fix. (This used to be commit 9b13dae5a9cec827f854d5d0eb77eb16709b39b9) --- source3/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 278d53be56..a02bd751c8 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -398,7 +398,8 @@ WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \ wrepld/partners.o WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) $(UBIQX_OBJ) \ - $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) + $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \ + $(LIBSAMBA_OBJ) SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ web/swat.o web/neg_lang.o -- cgit From 8838f54497d5cab4f1120cfc87f611b3e7e42698 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 21 Oct 2003 04:45:33 +0000 Subject: Merge of krb5_keytab entry key vs keyblock member check from HEAD. (This used to be commit 720f5e5629c54e851c3e9026dc88676795e44c8e) --- source3/configure.in | 9 +++++++++ source3/libads/kerberos_verify.c | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index f3b3f9272b..16b0760802 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -2654,6 +2654,15 @@ if test x"$with_ads_support" != x"no"; then [Whether in-memory keytabs are supported]) fi + AC_CHECK_MEMBER(krb5_keytab_entry.key, + AC_DEFINE(HAVE_KRB5_KEYTAB_ENTRY_KEY, 1, + [Whether krb5_keytab_entry has key member]), [], + [#include ]) + + AC_CHECK_MEMBER(krb5_keytab_entry.keyblock, + AC_DEFINE(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK, 1, + [Whether krb5_keytab_entry has keyblock member]), [], + [#include ]) if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support]) diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index 4ae89aa01f..cdea5a2fe4 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -71,10 +71,18 @@ static krb5_error_code create_keytab(krb5_context context, entry.principal = host_princ; entry.vno = kvno; - /* this will have to be detected in configure...heimdal - calls it keyblock, MIT calls it key, but it does not - matter we are creating keytabs with MIT */ - entry.keyblock = *key; + +#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK) +#error krb5_keytab_entry has no key or keyblock member +#endif + +#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */ + entry.key = *key; +#endif + +#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ + entry.keyblock = *key; +#endif DEBUG(10,("adding keytab-entry for (%s) with encryption type (%d)\n", host_princ_s, enctypes[i])); -- cgit From 87a6e23fcc9bffdb9947aa4d9ff8469eabdadb30 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 21 Oct 2003 04:46:23 +0000 Subject: Merge of mmap blacklist fix from HEAD. (This used to be commit ff29be16e74361b02b0b7fbd83e393d68ae5b897) --- source3/include/includes.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3') diff --git a/source3/include/includes.h b/source3/include/includes.h index 452b489547..fba2eabbe1 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -1319,4 +1319,11 @@ BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_conte #endif #define FALSE __ERROR__XX__DONT_USE_FALSE +/* If we have blacklisted mmap() try to avoid using it accidentally by + undefining the HAVE_MMAP symbol. */ + +#ifdef MMAP_BLACKLIST +#undef HAVE_MMAP +#endif + #endif /* _INCLUDES_H */ -- cgit From cc14d8c56151ee0e798dc2c9122d3ba8da982e7a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 21 Oct 2003 04:54:20 +0000 Subject: Merge of another fix from Monyo. (This used to be commit 8d4d8aed2baa4b81bde9b30399f946062fc14094) --- source3/intl/lang_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c index af70b529ff..b0e9e414de 100644 --- a/source3/intl/lang_tdb.c +++ b/source3/intl/lang_tdb.c @@ -242,7 +242,7 @@ void lang_msg_free(const char *msgstr) */ const char *lang_msg_rotate(const char *msgid) { -#define NUM_LANG_BUFS 4 +#define NUM_LANG_BUFS 16 char *msgstr; static pstring bufs[NUM_LANG_BUFS]; static int next; -- cgit From 2e9e9ff31bd865d4955b7b851a09c2b331f363f8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 21 Oct 2003 14:20:02 +0000 Subject: call initgroups before becomming the user; patch from Fabio Cecchi (This used to be commit e0db859a312207d961e3a581dfd15d9701bca16d) --- source3/web/cgi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3') diff --git a/source3/web/cgi.c b/source3/web/cgi.c index 212c2884b6..8e739cd224 100644 --- a/source3/web/cgi.c +++ b/source3/web/cgi.c @@ -342,6 +342,9 @@ static BOOL cgi_handle_authorization(char *line) * Password was ok. */ + if ( initgroups(pass->pw_name, pass->pw_gid) != 0 ) + goto err; + become_user_permanently(pass->pw_uid, pass->pw_gid); /* Save the users name */ -- cgit From 718634017933bbf39526b834981cde92cfe7a2da Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 21 Oct 2003 16:27:46 +0000 Subject: Fix typo (This used to be commit 26956cdef902819f94616c33694641752f0f14e9) --- source3/rpc_parse/parse_epmapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c index 02340430ec..61704136a0 100644 --- a/source3/rpc_parse/parse_epmapper.c +++ b/source3/rpc_parse/parse_epmapper.c @@ -343,7 +343,7 @@ BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array, } for (i = 0; i < array->count; i++) { - if (!epm_io_tower("tower", array->towers + 1, ps, depth)) + if (!epm_io_tower("tower", &array->towers[i], ps, depth)) return False; } -- cgit From 630a77e50f0d12e7f91f10ec68bbb836edf62791 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 17:40:48 +0000 Subject: Fix signing miss-sequence noticed by Stefan Metzmacher Jeremy. (This used to be commit 419834edee09567c8523ad3afba674a12504282d) --- source3/libsmb/smb_signing.c | 73 ++++++++++++++++---------------------------- source3/smbd/notify.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/process.c | 2 +- 4 files changed, 30 insertions(+), 49 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 8a4401ef19..91509f0fb8 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -25,7 +25,6 @@ struct outstanding_packet_lookup { uint16 mid; uint32 reply_seq_num; - BOOL deferred_packet; struct outstanding_packet_lookup *prev, *next; }; @@ -44,7 +43,7 @@ struct smb_basic_signing_context { }; static void store_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 reply_seq_num, BOOL deferred_pkt) + uint16 mid, uint32 reply_seq_num) { struct outstanding_packet_lookup *t; struct outstanding_packet_lookup *tmp; @@ -55,25 +54,20 @@ static void store_sequence_for_reply(struct outstanding_packet_lookup **list, DLIST_ADD_END(*list, t, tmp); t->mid = mid; t->reply_seq_num = reply_seq_num; - t->deferred_packet = deferred_pkt; - DEBUG(10,("store_sequence_for_reply: stored %sseq = %u mid = %u\n", - deferred_pkt ? "deferred " : "", + DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n", (unsigned int)reply_seq_num, (unsigned int)mid )); } static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 *reply_seq_num, BOOL *def) + uint16 mid, uint32 *reply_seq_num) { struct outstanding_packet_lookup *t; for (t = *list; t; t = t->next) { if (t->mid == mid) { *reply_seq_num = t->reply_seq_num; - if (def) - *def = t->deferred_packet; - DEBUG(10,("get_sequence_for_reply: found %sseq = %u mid = %u\n", - (t->deferred_packet) ? "deferred " : "", + DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); DLIST_REMOVE(*list, t); SAFE_FREE(t); @@ -83,22 +77,6 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, return False; } -/*********************************************************** - A reply is pending if there is a non-deferred packet on the queue. -************************************************************/ - -static BOOL is_reply_pending(struct outstanding_packet_lookup *list) -{ - for (; list; list = list->next) { - if (!list->deferred_packet) { - DEBUG(10,("is_reply_pending: True.\n")); - return True; - } - } - DEBUG(10,("is_reply_pending: False.\n")); - return False; -} - /*********************************************************** SMB signing - Common code before we set a new signing implementation ************************************************************/ @@ -329,8 +307,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) data->send_seq_num++; store_sequence_for_reply(&data->outstanding_packet_list, - SVAL(outbuf,smb_mid), - data->send_seq_num, False); + SVAL(outbuf,smb_mid), data->send_seq_num); data->send_seq_num++; } @@ -359,8 +336,7 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) if (data->trans_info) { reply_seq_number = data->trans_info->reply_seq_num; } else if (!get_sequence_for_reply(&data->outstanding_packet_list, - SVAL(inbuf, smb_mid), - &reply_seq_number, NULL)) { + SVAL(inbuf, smb_mid), &reply_seq_number)) { DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n", (unsigned int) SVAL(inbuf, smb_mid) )); return False; @@ -639,7 +615,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) mid = SVAL(outbuf, smb_mid); /* See if this is a reply for a deferred packet. */ - get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number, &was_deferred_packet); + was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number); if (data->trans_info && (data->trans_info->mid == mid)) { /* This is a reply in a trans stream. Use the sequence @@ -655,18 +631,21 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); /* cli->outbuf[smb_ss_field+2]=0; - Uncomment this to test if the remote server actually verifies signatures...*/ + Uncomment this to test if the remote client actually verifies signatures...*/ - if (!was_deferred_packet) { - if (!data->trans_info) { - /* Always increment if not in a trans stream. */ - data->send_seq_num++; - } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) { - /* Increment if this is the first reply in a trans stream or a - * packet that doesn't belong to this stream (different mid). */ - data->send_seq_num++; - } - } + /* Don't mess with the sequence number for a deferred packet. */ + if (was_deferred_packet) { + return; + } + + if (!data->trans_info) { + /* Always increment if not in a trans stream. */ + data->send_seq_num++; + } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) { + /* Increment if this is the first reply in a trans stream or a + * packet that doesn't belong to this stream (different mid). */ + data->send_seq_num++; + } } /*********************************************************** @@ -721,8 +700,10 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) * isn't a reply pending we need to re-sync the sequence * number. */ - if (is_oplock_break(inbuf) && !is_reply_pending(data->outstanding_packet_list)) + if (is_oplock_break(inbuf)) { + DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num)); data->send_seq_num++; + } } saved_seq = reply_seq_number; @@ -820,7 +801,7 @@ void srv_calculate_sign_mac(char *outbuf) Called by server to defer an outgoing packet. ************************************************************/ -void srv_defer_sign_response(uint16 mid, BOOL deferred_packet) +void srv_defer_sign_response(uint16 mid) { struct smb_basic_signing_context *data; @@ -833,7 +814,7 @@ void srv_defer_sign_response(uint16 mid, BOOL deferred_packet) return; store_sequence_for_reply(&data->outstanding_packet_list, - mid, data->send_seq_num, deferred_packet); + mid, data->send_seq_num); data->send_seq_num++; } @@ -857,7 +838,7 @@ void srv_cancel_sign_response(uint16 mid) DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid )); - while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq,NULL)) + while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq)) ; } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ca6f2b783f..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid), True); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 71af23aaf9..ef7ace862a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,7 +631,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* This isn't a real deferred packet as it's response will also increment * the sequence. */ - srv_defer_sign_response(get_current_mid(), False); + srv_defer_sign_response(get_current_mid()); /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3c15cd1833..43ffb82bd7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -97,7 +97,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) ubi_slAddTail( list_head, msg); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid), True); + srv_defer_sign_response(SVAL(buf,smb_mid)); return True; } -- cgit From 989b57f783adada15db645f60e9aafc3e83cc6ce Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 21 Oct 2003 17:59:08 +0000 Subject: Add server side support for epmapper pipe. Currently only does a fixed mapping, but this is the base for changes to come. (This used to be commit 73882e970a3aea1c3c9f34779b4220bbf28f6dad) --- source3/Makefile.in | 14 ++++-- source3/configure.in | 4 +- source3/rpc_server/srv_epmapper.c | 88 ++++++++++++++++++++++++++++++++++++ source3/rpc_server/srv_epmapper_nt.c | 70 ++++++++++++++++++++++++++++ source3/rpc_server/srv_pipe.c | 3 ++ source3/smbd/nttrans.c | 1 + 6 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 source3/rpc_server/srv_epmapper.c create mode 100644 source3/rpc_server/srv_epmapper_nt.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index a02bd751c8..10c07d05eb 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -264,6 +264,8 @@ RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \ RPC_ECHO_OBJ = rpc_server/srv_echo.o rpc_server/srv_echo_nt.o +RPC_EPMAPPER_OBJ = rpc_server/srv_epmapper.o rpc_server/srv_epmapper_nt.o + RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ) # this includes only the low level parse code, not stuff @@ -580,9 +582,10 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \ $(READLINE_OBJ) $(PROFILE_OBJ) $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \ $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ - $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \ - $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ - $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o + $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \ + $(RPC_LSA_DS_OBJ) $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) \ + $(RPC_SPOOLSS_OBJ) $(RPC_ECHO_OBJ) $(RPC_EPMAPPER_OBJ) \ + $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \ $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) @@ -1005,6 +1008,11 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_ECHO_OBJ) -lc \ @SONAMEFLAG@`basename $@` +bin/librpc_epmapper.@SHLIBEXT@: $(RPC_EPMAPPER_OBJ) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_EPMAPPER_OBJ) -lc \ + @SONAMEFLAG@`basename $@` + bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy @echo "Linking $@" @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) diff --git a/source3/configure.in b/source3/configure.in index 16b0760802..01c71b3149 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -296,7 +296,7 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin pdb_gums gums_tdbsam2" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_epmapper auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin pdb_gums gums_tdbsam2" dnl These are preferably build shared, and static if dlopen() is not available default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437" @@ -4128,6 +4128,8 @@ SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC) SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) +SMB_MODULE(rpc_epmapper, \$(RPC_EPMAPPER_OBJ), "bin/librpc_epmapper.$SHLIBEXT", + RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/idmap_ldap.$SHLIBEXT", IDMAP) diff --git a/source3/rpc_server/srv_epmapper.c b/source3/rpc_server/srv_epmapper.c new file mode 100644 index 0000000000..70de092850 --- /dev/null +++ b/source3/rpc_server/srv_epmapper.c @@ -0,0 +1,88 @@ + +/* + Unix SMB/CIFS implementation. + Samba end point mapper utility and mapping functions + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/***************************************************************** + api_handle_map_req - handles standard epm mapping request +******************************************************************/ +static BOOL api_handle_map_req(pipes_struct * p) +{ + + EPM_Q_MAP q_in; + EPM_R_MAP q_out; + + prs_struct *in_data = &p->in_data.data; + prs_struct *ret_data = &p->out_data.rdata; + + ZERO_STRUCT(q_in); + ZERO_STRUCT(q_out); + + /* process input request and parse packet */ + + if (!epm_io_q_map("", &q_in, in_data, 0)) { + DEBUG(0, + ("api_handle_map_request: unable to unmarshall EPMD_MAP\n")); + return False; + } + + _epm_map(p, &q_in, &q_out); + + if (!epm_io_r_map("", &q_out, ret_data, 0)) { + DEBUG(0, + ("api_handle_map_req: unable to marshall EPMD_MAP\n")); + return False; + } + + return True; +} + +/*******************************************************************/ +/* \pipe\epmapper commands */ +/*******************************************************************/ +/* opnum is 3 on map request */ + +struct api_struct api_epmapper_cmds[] = { + {"MAP_PIPE_NAME", EPM_MAP_PIPE_NAME, api_handle_map_req}, +}; + +/*******************************************************************/ +/* */ +/*******************************************************************/ + +void epm_get_pipe_fns(struct api_struct **funcs, int *n_funcs) +{ + *funcs = api_epmapper_cmds; + *n_funcs = sizeof(api_epmapper_cmds) / sizeof(struct api_struct); +} + +/*******************************************************************/ +/* */ +/*******************************************************************/ + +NTSTATUS rpc_epmapper_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, + EPM_PIPE_NM, EPM_PIPE_NM, + api_epmapper_cmds, + sizeof(api_epmapper_cmds) / + sizeof(struct api_struct)); +} diff --git a/source3/rpc_server/srv_epmapper_nt.c b/source3/rpc_server/srv_epmapper_nt.c new file mode 100644 index 0000000000..1b72a5ed41 --- /dev/null +++ b/source3/rpc_server/srv_epmapper_nt.c @@ -0,0 +1,70 @@ + +/* + Unix SMB/CIFS implementation. + Samba end point mapper utility and mapping functions + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/*******************************************************************/ +/* _epm_map - fill out mapping on input and output structs */ +/*******************************************************************/ +void _epm_map(pipes_struct *ps, const EPM_Q_MAP *q_u, EPM_R_MAP *r_u) +{ + int i; + uint8 target_address[] = { 9, 53, 95, 27 }; + EPM_FLOOR *floors = talloc(ps->mem_ctx, sizeof(EPM_FLOOR) * + q_u->tower->num_floors); + EPM_TOWER *towers = talloc(ps->mem_ctx, + sizeof(EPM_TOWER) * MAX_TOWERS); + EPM_TOWER_ARRAY array; + + if (!floors || !towers) { + DEBUG(0, ("_epm_map: talloc failed!\n")); + return; + } + + for (i = 0; i < q_u->tower->num_floors; i++) { + switch (q_u->tower->floors[i].lhs.protocol) { + case EPM_FLOOR_UUID: + init_epm_floor_uuid(&floors[i], + &q_u->tower->floors[i]. + lhs.uuid.uuid, + q_u->tower->floors[i]. + lhs.uuid.version); + break; + case EPM_FLOOR_RPC: + init_epm_floor_rpc(&floors[i]); + break; + case EPM_FLOOR_TCP: + /* for now map all requests to port 135 */ + init_epm_floor_tcp(&floors[i], 135); + break; + case EPM_FLOOR_IP: + init_epm_floor_ip(&floors[i], target_address); + break; + } + } + + init_epm_tower(ps->mem_ctx, &towers[0], floors, 5); + init_epm_tower_array(ps->mem_ctx, &array, towers, 1); + init_epm_r_map(ps->mem_ctx, r_u, &q_u->term_handle, &array, 1, 0); + + return; + +} diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 96261c665f..444c35987a 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1603,6 +1603,9 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) echo_get_pipe_fns( &cmds, &n_cmds ); break; #endif + case PI_EPM: + epm_get_pipe_fns( &cmds, &n_cmds ); + break; default: DEBUG(0,("get_pipe_fns: Unknown pipe index! [%d]\n", idx)); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19af61f190..e7d7c20f6b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -43,6 +43,7 @@ static const char *known_nt_pipes[] = { "\\spoolss", "\\netdfs", "\\rpcecho", + "\\epmapper", NULL }; -- cgit From af4263e46e744bde8d637a2fff016f1a6ca3e543 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 20:17:42 +0000 Subject: Merge tridge's AIX fixes. Jeremy. (This used to be commit 96cefb4542debd8902d9bc0cd09bb01c7a41cc69) --- source3/nsswitch/winbind_nss_aix.c | 480 ++++++++++++++++++------------------- 1 file changed, 231 insertions(+), 249 deletions(-) (limited to 'source3') diff --git a/source3/nsswitch/winbind_nss_aix.c b/source3/nsswitch/winbind_nss_aix.c index 8b5bc7a50c..3d2f01b93c 100644 --- a/source3/nsswitch/winbind_nss_aix.c +++ b/source3/nsswitch/winbind_nss_aix.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2003 Copyright (C) Steve Roylance 2003 + Copyright (C) Andrew Tridgell 2003 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -23,182 +24,188 @@ Boston, MA 02111-1307, USA. */ +/* + see + http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm + for information in the interface that this module implements +*/ + #include #include #include #include +#include #include "winbind_client.h" -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -static struct passwd *fill_pwent(struct winbindd_pw *pw) -{ - struct passwd *result; - - if (!(result = malloc(sizeof(struct passwd)))) - goto out; - - ZERO_STRUCTP(result); - - /* User name */ +/* + the documentation doesn't say so, but experimentation shows that all + of the functions need to return static data, and the area can be + freed only when the same function is called again, or the close + method is called on the module. Note that this matches the standard + behaviour of functions like getpwnam(). + + The most puzzling thing about this AIX interface is that it seems to + offer no way of providing a user or group enumeration method. You + can find out any amount of detail about a user or group once you + know the name, but you can't obtain a list of those names. If anyone + does find out how to do this then please let me know (yes, I should + be able to find out as I work for IBM, and this is an IBM interface, + but finding the right person to ask is a mammoth task!) + + tridge@samba.org October 2003 +*/ - if ((result->pw_name = malloc(strlen(pw->pw_name) + 1)) == NULL) - goto out; - - strcpy(result->pw_name, pw->pw_name); - /* Password */ +/* + each function uses one of the following lists of memory, declared + static in each backend method. This allows the function to destroy + the memory when that backend is called next time +*/ +struct mem_list { + struct mem_list *next, *prev; + void *p; +}; - if ((result->pw_passwd = malloc(strlen(pw->pw_passwd) + 1)) == NULL) - goto out; - - strcpy(result->pw_passwd, pw->pw_passwd); - - /* [ug]id */ - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; +/* allocate some memory on a mem_list */ +static void *list_alloc(struct mem_list **list, size_t size) +{ + struct mem_list *m; + m = malloc(sizeof(*m)); + if (!m) { + errno = ENOMEM; + return NULL; + } + m->p = malloc(size); + if (!m->p) { + errno = ENOMEM; + free(m); + return NULL; + } + m->next = *list; + m->prev = NULL; + if (*list) { + (*list)->prev = m; + } + (*list) = m; + return m->p; +} - /* GECOS */ +/* duplicate a string using list_alloc() */ +static char *list_strdup(struct mem_list **list, const char *s) +{ + char *ret = list_alloc(list, strlen(s)+1); + if (!ret) return NULL; + strcpy(ret, s); + return ret; +} - if ((result->pw_gecos = malloc(strlen(pw->pw_gecos) + 1)) == NULL) - goto out; +/* destroy a mem_list */ +static void list_destory(struct mem_list **list) +{ + struct mem_list *m, *next; + for (m=*list; m; m=next) { + next = m->next; + free(m->p); + free(m); + } + (*list) = NULL; +} - strcpy(result->pw_gecos, pw->pw_gecos); - - /* Home directory */ - - if ((result->pw_dir = malloc(strlen(pw->pw_dir) + 1)) == NULL) - goto out; - strcpy(result->pw_dir, pw->pw_dir); +#define HANDLE_ERRORS(ret) do { \ + if ((ret) == NSS_STATUS_NOTFOUND) { \ + errno = ENOENT; \ + return NULL; \ + } else if ((ret) != NSS_STATUS_SUCCESS) { \ + errno = EIO; \ + return NULL; \ + } \ +} while (0) - /* Logon shell */ - - if ((result->pw_shell = malloc(strlen(pw->pw_shell) + 1)) == NULL) - goto out; - - strcpy(result->pw_shell, pw->pw_shell); - - return result; - - /* A memory allocation failed, undo succesfull allocations and - return NULL */ - -out: - errno = ENOMEM; - SAFE_FREE(result->pw_dir); - SAFE_FREE(result->pw_gecos); - SAFE_FREE(result->pw_passwd); - SAFE_FREE(result->pw_name); - SAFE_FREE(result); - - return NULL; -} - -static BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize) +/* + fill a struct passwd from a winbindd_pw struct, using memory from a mem_list +*/ +static struct passwd *fill_pwent(struct mem_list **list, struct winbindd_pw *pw) { - char *s; - BOOL quoted; - size_t len=1; + struct passwd *result; - if (!ptr) return(False); + if (!(result = list_alloc(list, sizeof(struct passwd)))) { + return NULL; + } - s = *ptr; + ZERO_STRUCTP(result); - /* default to simple separators */ - if (!sep) sep = " \t\n\r"; + result->pw_uid = pw->pw_uid; + result->pw_gid = pw->pw_gid; - /* find the first non sep char */ - while (*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (! *s) return(False); - - /* copy over the token */ - for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { - if (*s == '\"') { - quoted = !quoted; - } else { - len++; - *buff++ = *s; - } + /* strings */ + if ((result->pw_name = list_strdup(list, pw->pw_name)) == NULL || + (result->pw_passwd = list_strdup(list, pw->pw_passwd)) == NULL || + (result->pw_gecos = list_strdup(list, pw->pw_gecos)) == NULL || + (result->pw_dir = list_strdup(list, pw->pw_dir)) == NULL || + (result->pw_shell = list_strdup(list, pw->pw_shell)) == NULL) { + return NULL; } - *ptr = (*s) ? s+1 : s; - *buff = 0; - - return(True); + return result; } -static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem) + +/* + fill a struct group from a winbindd_pw struct, using memory from a mem_list +*/ +static struct group *fill_grent(struct mem_list **list, struct winbindd_gr *gr, char *gr_mem) { - fstring name; int i; char *tst; struct group *result; - - if (!(result = malloc(sizeof(struct group)))) - goto out; + char *name, *p; - ZERO_STRUCTP(result); - - /* Group name */ - - if ((result->gr_name = malloc(strlen(gr->gr_name) + 1)) == NULL) - goto out; - - strcpy(result->gr_name, gr->gr_name); - - /* Password */ - - if ((result->gr_passwd = malloc(strlen(gr->gr_passwd) + 1)) == NULL) - goto out; - - strcpy(result->gr_passwd, gr->gr_passwd); + if (!(result = list_alloc(list, sizeof(struct group)))) { + return NULL; + } - /* gid */ + ZERO_STRUCTP(result); result->gr_gid = gr->gr_gid; - /* Group membership */ + /* Group name */ + if ((result->gr_name = list_strdup(list, gr->gr_name)) == NULL || + (result->gr_passwd = list_strdup(list, gr->gr_passwd)) == NULL) { + return NULL; + } + /* Group membership */ if ((gr->num_gr_mem < 0) || !gr_mem) { gr->num_gr_mem = 0; } if (gr->num_gr_mem == 0) { - - /* Group is empty */ - - *(result->gr_mem) = NULL; + /* Group is empty */ return result; } - if ((tst = malloc(((gr->num_gr_mem + 1) * sizeof(char *)))) == NULL) - goto out; + tst = list_alloc(list, (gr->num_gr_mem + 1) * sizeof(char *)); + if (!tst) { + return NULL; + } result->gr_mem = (char **)tst; /* Start looking at extra data */ - - i = 0; - - while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) { - - /* Allocate space for member */ - - if (((result->gr_mem)[i] = - malloc(strlen(name) + 1)) == NULL) { - for ( i -= 1; i >= 0; i--) - SAFE_FREE((result->gr_mem)[i]); - goto out; - - } - - strcpy((result->gr_mem)[i], name); + i=0; + for (name = strtok_r(gr_mem, ",", &p); + name; + name = strtok_r(NULL, ",", &p)) { + if (i >= gr->num_gr_mem) { + return NULL; + } + (result->gr_mem)[i] = list_strdup(list, name); + if ((result->gr_mem)[i] == NULL) { + return NULL; + } i++; } @@ -206,140 +213,123 @@ static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem) (result->gr_mem)[i] = NULL; return result; - - /* A memory allocation failed, undo succesfull allocations and - return NULL */ - -out: - errno = ENOMEM; - SAFE_FREE(tst); - SAFE_FREE(result->gr_passwd); - SAFE_FREE(result->gr_name); - SAFE_FREE(result); - - return NULL; } -static struct group * -wb_aix_getgrgid (gid_t gid) +/* take a group id and return a filled struct group */ +static struct group *wb_aix_getgrgid(gid_t gid) { -/* take a group id and return a filled struct group */ - + static struct mem_list *list; struct winbindd_response response; struct winbindd_request request; + struct group *grp; NSS_STATUS ret; + list_destory(&list); + ZERO_STRUCT(response); ZERO_STRUCT(request); request.data.gid = gid; ret = winbindd_request(WINBINDD_GETGRGID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - return fill_grent(&response.data.gr, response.extra_data); - } else if (ret == NSS_STATUS_NOTFOUND) { - errno = ENOENT; - } else { - errno = EIO; - } - - return NULL; + + HANDLE_ERRORS(ret); + + grp = fill_grent(&list, &response.data.gr, response.extra_data); + + free_response(&response); + + return grp; } -static struct group * -wb_aix_getgrnam (const char *name) -{ /* take a group name and return a filled struct group */ - +static struct group *wb_aix_getgrnam(const char *name) +{ + static struct mem_list *list; struct winbindd_response response; struct winbindd_request request; NSS_STATUS ret; - + struct group *grp; + + list_destory(&list); + ZERO_STRUCT(response); ZERO_STRUCT(request); - strncpy(request.data.groupname, name, - sizeof(request.data.groupname)); - request.data.groupname - [sizeof(request.data.groupname) - 1] = '\0'; + if (strlen(name)+1 > sizeof(request.data.groupname)) { + errno = EINVAL; + return NULL; + } + strcpy(request.data.groupname, name); ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response); - if (ret == NSS_STATUS_SUCCESS) { - return fill_grent(&response.data.gr, response.extra_data); - } else if (ret == NSS_STATUS_NOTFOUND) { - errno = ENOENT; - } else { - errno = EIO; - } - - return NULL; + HANDLE_ERRORS(ret); + + grp = fill_grent(&list, &response.data.gr, response.extra_data); + + free_response(&response); + + return grp; } -static char * -wb_aix_getgrset (const char *user) + +/* take a username and return a string containing a comma-separated + list of group id numbers to which the user belongs */ +static char *wb_aix_getgrset(char *user) { -/* take a username and return a string containing a comma-separated list of - group id numbers to which the user belongs */ - + static struct mem_list *list; struct winbindd_response response; struct winbindd_request request; NSS_STATUS ret; + int i, idx; + char *tmpbuf; + int num_gids; + gid_t *gid_list; - strncpy(request.data.username, user, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; + list_destory(&list); + + if (strlen(user)+1 > sizeof(request.data.username)) { + errno = EINVAL; + return NULL; + } + strcpy(request.data.username, user); ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - if (ret == NSS_STATUS_SUCCESS ) { - int i, idx = 0; - char *tmpbuf, *result; - - int num_gids = response.data.num_entries; - gid_t *gid_list = (gid_t *)response.extra_data; + HANDLE_ERRORS(ret); + + num_gids = response.data.num_entries; + gid_list = (gid_t *)response.extra_data; - /* allocate a space large enough to contruct the string */ - if (!(tmpbuf = malloc(num_gids*12))) { - errno = ENOMEM; - return NULL; - } - idx += sprintf(tmpbuf, "%d", gid_list[0]); - for (i = 1; i < num_gids; i++) { - tmpbuf[idx++] = ','; - idx += sprintf(tmpbuf+idx, "%d", gid_list[i]); - } - tmpbuf[idx] = '\0'; - if (!(result = malloc(idx+1))) { - /* allocate a string the right size to return, but - if that fails may as well return our working buffer - because it contains the same thing */ - return tmpbuf; - } - strcpy(result, tmpbuf); - SAFE_FREE(tmpbuf); - return result; - } else if (ret == NSS_STATUS_NOTFOUND) { - errno = ENOENT; - } else { - errno = EIO; + /* allocate a space large enough to contruct the string */ + tmpbuf = list_alloc(&list, num_gids*12); + if (!tmpbuf) { + return NULL; } - - return NULL; + + for (idx=i=0; i < num_gids-1; i++) { + idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]); + } + idx += sprintf(tmpbuf+idx, "%u", gid_list[i]); + + free_response(&response); + + return tmpbuf; } -static struct passwd * -wb_aix_getpwuid (uid_t uid) + +/* take a uid and return a filled struct passwd */ +static struct passwd *wb_aix_getpwuid(uid_t uid) { -/* take a uid and return a filled struct passwd */ - + static struct mem_list *list; struct winbindd_response response; struct winbindd_request request; NSS_STATUS ret; + + list_destory(&list); ZERO_STRUCT(response); ZERO_STRUCT(request); @@ -347,55 +337,46 @@ wb_aix_getpwuid (uid_t uid) request.data.uid = uid; ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - return fill_pwent(&response.data.pw); - } else if (ret == NSS_STATUS_NOTFOUND ) { - errno = ENOENT; - } else { - errno = EIO; - } - - return NULL; + + HANDLE_ERRORS(ret); + + return fill_pwent(&list, &response.data.pw); } -static struct passwd * -wb_aix_getpwnam (const char *name) -{ -/* take a username and return a filled struct passwd */ +/* take a username and return a filled struct passwd */ +static struct passwd *wb_aix_getpwnam(const char *name) +{ + static struct mem_list *list; struct winbindd_response response; struct winbindd_request request; NSS_STATUS ret; + + list_destory(&list); ZERO_STRUCT(response); ZERO_STRUCT(request); - strncpy(request.data.username, name, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; + if (strlen(name)+1 > sizeof(request.data.username)) { + errno = EINVAL; + return NULL; + } + + strcpy(request.data.username, name); ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response); + + HANDLE_ERRORS(ret); - if (ret == NSS_STATUS_SUCCESS ) { - return fill_pwent(&response.data.pw); - } else if (ret == NSS_STATUS_NOTFOUND) { - errno = ENOENT; - } else { - errno = EIO; - } - - return NULL; + return fill_pwent(&list, &response.data.pw); } -int -wb_aix_init (struct secmethod_table *methods) +int wb_aix_init(struct secmethod_table *methods) { - memset(methods, 0, sizeof(*methods)); + ZERO_STRUCTP(methods); /* identification methods, this is the minimum requried for a - working module */ + working module */ methods->method_getgrgid = wb_aix_getgrgid; methods->method_getgrnam = wb_aix_getgrnam; @@ -405,3 +386,4 @@ wb_aix_init (struct secmethod_table *methods) return AUTH_SUCCESS; } + -- cgit From db8e98175c47cddd89e07b5e1c4c8b5f88651ccc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 21:18:58 +0000 Subject: Patch from Stefan Metzmacher to fix signing problems when reverse connecting back to a client for printer notify. Jeremy. (This used to be commit 7fde193efeb856ec325d5d563f1e710c45dc65d7) --- source3/lib/util_sock.c | 19 +++++++++++++++++-- source3/libsmb/clientgen.c | 2 +- source3/rpc_server/srv_spoolss_nt.c | 3 ++- source3/smbd/blocking.c | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index b8b8471708..5a1f631ba4 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -497,9 +497,10 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) BUFFER_SIZE+SAFETY_MARGIN. The timeout is in milliseconds. This function will return on receipt of a session keepalive packet. + Doesn't check the MAC on signed packets. ****************************************************************************/ -BOOL receive_smb(int fd,char *buffer, unsigned int timeout) +BOOL receive_smb_raw(int fd,char *buffer, unsigned int timeout) { ssize_t len,ret; @@ -509,7 +510,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) len = read_smb_length_return_keepalive(fd,buffer,timeout); if (len < 0) { - DEBUG(10,("receive_smb: length < 0!\n")); + DEBUG(10,("receive_smb_raw: length < 0!\n")); /* * Correct fix. smb_read_error may have already been @@ -552,6 +553,20 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) } } + return True; +} + +/**************************************************************************** + Wrapper for receive_smb_raw(). + Checks the MAC on signed packets. +****************************************************************************/ + +BOOL receive_smb(int fd,char *buffer, unsigned int timeout) +{ + if (!receive_smb_raw(fd, buffer, timeout)) { + return False; + } + /* Check the incoming SMB signature. */ if (!srv_check_sign_mac(buffer)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n")); diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 0a134f715d..9b54acf775 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -59,7 +59,7 @@ static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout) BOOL ret; for(;;) { - ret = receive_smb(fd, buffer, timeout); + ret = receive_smb_raw(fd, buffer, timeout); if (!ret) { DEBUG(10,("client_receive_smb failed\n")); diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index f2fb02176b..15578f6148 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -2598,7 +2598,8 @@ static BOOL spoolss_connect_to_client(struct cli_state *the_cli, } the_cli->protocol = PROTOCOL_NT1; - + cli_setup_signing_state(the_cli, lp_client_signing()); + if (!cli_negprot(the_cli)) { DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) )); cli_shutdown(the_cli); diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index f43790bfe0..c0512d5539 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -149,7 +149,7 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid), True); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; } -- cgit From 3029c5bbd8bd0e5459612b4cf6208115ca867c51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 23:14:39 +0000 Subject: Fix for bug #64, Win9x Nexus tools not working against Samba3.0. Missing map in errormap for ERROR_MORE_DATA -> ERRDOS, ERRmoredata. Jeremy. (This used to be commit 8458f4c52f32ef192287ddb8371638f42a370c6f) --- source3/libsmb/errormap.c | 4 ++++ source3/smbd/ipc.c | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c index 4d9a717e1c..116d2cefe1 100644 --- a/source3/libsmb/errormap.c +++ b/source3/libsmb/errormap.c @@ -98,6 +98,10 @@ static const struct { */ {ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, +/* + * Not an official error, as only bit 0x80000000, not bits 0xC0000000 are set. + */ + {ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW}, {ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bc828d2e8e..86d982b022 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -96,7 +96,7 @@ void send_trans_reply(char *outbuf, align = ((this_lparam)%4); if (buffer_too_large) { - ERROR_NT(STATUS_BUFFER_OVERFLOW); + ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata); } set_message(outbuf,10,1+align+this_ldata+this_lparam,True); @@ -281,6 +281,14 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, subcommand = ((int)setup[0]) & 0xFFFF; if(!(p = get_rpc_pipe(pnum))) { + if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) { + /* Win9x does this call with a unicode pipe name, not a pnum. */ + /* Just return success for now... */ + DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + return -1; + } + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); return api_no_reply(outbuf, mdrcnt); } -- cgit From 2fef82e5df4f4e85cc21734189b54b7be15f42cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 22 Oct 2003 07:31:17 +0000 Subject: Merge from 3_0: In cli_lsa_lookup_sids don't leave the domain field uninitialized if some sid could not be mapped. Otherwise this call is unnecessarily complicated to call. Volker (This used to be commit 198b01fc54ce7a5beeddc680b30da291639b4eda) --- source3/rpc_client/cli_lsarpc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 65115419b4..ab4fbad613 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -322,6 +322,7 @@ NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, } else { (*names)[i] = NULL; + (*domains)[i] = NULL; (*types)[i] = SID_NAME_UNKNOWN; } } -- cgit From 356e0437674d369ab90001910e257bfaf11cafe6 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 22 Oct 2003 15:52:36 +0000 Subject: Fix segfault in mount.cifs helper when there is no options specified during mount (This used to be commit a3b67626018ade2a823311b65202ab7f488ca0a7) --- source3/client/mount.cifs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index 7ab17a2b02..43b20e9d50 100755 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -501,7 +501,7 @@ int main(int argc, char ** argv) ipaddr = parse_server(share_name); /* if(share_name == NULL) return 1; */ - if (parse_options(strdup(orgoptions))) + if (orgoptions && parse_options(strdup(orgoptions))) return 1; if(got_user == 0) -- cgit From bca9e7d3258058594daaaedd2518fcb2c793ded0 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 22 Oct 2003 20:59:46 +0000 Subject: Be sure referent ID is updated for incoming structures, too. (This used to be commit 00e0aba2cf97e686a0b6b4d7bab50afbc5e97ac1) --- source3/rpc_parse/parse_epmapper.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c index 61704136a0..7a5f147c50 100644 --- a/source3/rpc_parse/parse_epmapper.c +++ b/source3/rpc_parse/parse_epmapper.c @@ -327,9 +327,17 @@ BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array, return False; } } - for (i=0; i < array->count; i++) - if (!prs_uint32("ref_id", ps, depth, &array->tower_ref_ids[i])) + for (i=0; i < array->count; i++) { + if (!prs_uint32("ref_id", ps, depth, &array->tower_ref_ids[i])) { return False; + } else { + if (array->tower_ref_ids[i] > internal_referent_id) { + internal_referent_id = array->tower_ref_ids[i]; + } + } + } + + if (!prs_set_offset(ps, prs_offset(ps) + array->offset)) return False; @@ -418,8 +426,10 @@ BOOL epm_io_q_map(const char *desc, EPM_Q_MAP *io_map, prs_struct *ps, if (!epm_io_handle("handle", &io_map->handle, ps, depth)) return False; - if (!prs_uint32("max_towers", ps, 0, &io_map->tower_ref_id)) + if (!prs_uint32("referent_id", ps, 0, &io_map->tower_ref_id)) return False; + if (io_map->tower_ref_id > internal_referent_id) + internal_referent_id = io_map->tower_ref_id; /* HACK: We need a more elegant way of doing this */ if (UNMARSHALLING(ps)) { -- cgit From 2710c35e549bb7775a8efe3265b105e594ad26ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Oct 2003 23:38:18 +0000 Subject: Put strcasecmp/strncasecmp on the banned list (except for needed calls in iconv.c and nsswitch/). Using them means you're not thinking about multibyte at all and I really want to discourage that. Jeremy. (This used to be commit 5c050a735f86927c7ef2a98b6f3a56abe39e4674) --- source3/auth/auth_builtin.c | 2 +- source3/include/safe_string.h | 14 ++++++++++++++ source3/lib/access.c | 20 ++++++++++---------- source3/lib/charcnv.c | 2 +- source3/lib/iconv.c | 6 ++++++ source3/lib/smbldap.c | 4 ++-- source3/lib/substitute.c | 4 ++-- source3/lib/util_sock.c | 4 ++-- source3/libads/ads_struct.c | 4 ++-- source3/libads/ldap.c | 6 +++--- source3/libsmb/namequery_dc.c | 2 +- source3/msdfs/msdfs.c | 6 +++--- source3/nmbd/nmbd_elections.c | 2 +- source3/nsswitch/winbindd_rpc.c | 2 +- source3/nsswitch/winbindd_util.c | 8 ++++---- source3/param/loadparm.c | 2 +- source3/passdb/pdb_ldap.c | 2 +- source3/passdb/pdb_smbpasswd.c | 2 +- source3/smbd/mangle_hash2.c | 2 +- source3/smbd/sesssetup.c | 2 +- source3/smbwrapper/smbw_dir.c | 4 ++-- source3/torture/mangle_test.c | 2 +- source3/utils/net.c | 8 ++++---- source3/utils/smbcquotas.c | 14 +++++++------- source3/web/cgi.c | 22 +++++++++++----------- 25 files changed, 83 insertions(+), 63 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c index f7cdfe3fd2..96c2221652 100644 --- a/source3/auth/auth_builtin.c +++ b/source3/auth/auth_builtin.c @@ -86,7 +86,7 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_ long error_num; fstrcpy(user, user_info->smb_name.str); - if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { + if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) { strupper_m(user); return nt_status_string_to_code(user); } diff --git a/source3/include/safe_string.h b/source3/include/safe_string.h index 07578b2424..cb3f37c484 100644 --- a/source3/include/safe_string.h +++ b/source3/include/safe_string.h @@ -47,6 +47,20 @@ #endif /* sprintf */ #define sprintf __ERROR__XX__NEVER_USE_SPRINTF__; +/* + * strcasecmp/strncasecmp aren't an error, but it means you're not thinking about + * multibyte. Don't use them. JRA. + */ +#ifdef strcasecmp +#undef strcasecmp +#endif +#define strcasecmp __ERROR__XX__NEVER_USE_STRCASECMP__; + +#ifdef strncasecmp +#undef strncasecmp +#endif +#define strncasecmp __ERROR__XX__NEVER_USE_STRCASECMP__; + #endif /* !_SPLINT_ */ #ifdef DEVELOPER diff --git a/source3/lib/access.c b/source3/lib/access.c index a874c8b1e2..62414726fb 100644 --- a/source3/lib/access.c +++ b/source3/lib/access.c @@ -71,7 +71,7 @@ static BOOL string_match(const char *tok,const char *s, char *invalid_char) if (tok[0] == '.') { /* domain: match last fields */ if ((str_len = strlen(s)) > (tok_len = strlen(tok)) - && strcasecmp(tok, s + str_len - tok_len) == 0) + && strequal(tok, s + str_len - tok_len)) return (True); } else if (tok[0] == '@') { /* netgroup: look it up */ #ifdef HAVE_NETGROUP @@ -107,14 +107,14 @@ static BOOL string_match(const char *tok,const char *s, char *invalid_char) DEBUG(0,("access: netgroup support is not configured\n")); return (False); #endif - } else if (strcasecmp(tok, "ALL") == 0) { /* all: match any */ + } else if (strequal(tok, "ALL")) { /* all: match any */ return (True); - } else if (strcasecmp(tok, "FAIL") == 0) { /* fail: match any */ + } else if (strequal(tok, "FAIL")) { /* fail: match any */ return (FAIL); - } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ - if (strchr_m(s, '.') == 0 && strcasecmp(s, "unknown") != 0) + } else if (strequal(tok, "LOCAL")) { /* local: no dots */ + if (strchr_m(s, '.') == 0 && !strequal(s, "unknown")) return (True); - } else if (!strcasecmp(tok, s)) { /* match host name or address */ + } else if (!strequal(tok, s)) { /* match host name or address */ return (True); } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ if (strncmp(tok, s, tok_len) == 0) @@ -175,7 +175,7 @@ static BOOL list_match(const char **list,const char *item, */ for (; *list ; list++) { - if (strcasecmp(*list, "EXCEPT") == 0) /* EXCEPT: give up */ + if (strequal(*list, "EXCEPT")) /* EXCEPT: give up */ break; if ((match = (*match_fn) (*list, item))) /* True or FAIL */ break; @@ -183,7 +183,7 @@ static BOOL list_match(const char **list,const char *item, /* Process exceptions to True or FAIL matches. */ if (match != False) { - while (*list && strcasecmp(*list, "EXCEPT")) + while (*list && !strequal(*list, "EXCEPT")) list++; for (; *list; list++) { @@ -275,8 +275,8 @@ static BOOL only_ipaddrs_in_list(const char** list) for (; *list ; list++) { /* factor out the special strings */ - if (!strcasecmp(*list, "ALL") || !strcasecmp(*list, "FAIL") || - !strcasecmp(*list, "EXCEPT")) { + if (strequal(*list, "ALL") || strequal(*list, "FAIL") || + strequal(*list, "EXCEPT")) { continue; } diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index dafc88fb77..9d15c6daa0 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -56,7 +56,7 @@ static const char *charset_name(charset_t ch) else if (ch == CH_UTF8) ret = "UTF8"; #if defined(HAVE_NL_LANGINFO) && defined(CODESET) - if (ret && strcasecmp(ret, "LOCALE") == 0) { + if (ret && !strcmp(ret, "LOCALE")) { const char *ln = NULL; #ifdef HAVE_SETLOCALE diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 0326ca7061..9f6db79ee2 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -21,6 +21,12 @@ #include "includes.h" +/* + * We have to use strcasecmp here as the character conversions + * haven't been initialised yet. JRA. + */ + +#undef strcasecmp /** * @file diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 781e6b976c..8f58e80dde 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -350,7 +350,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw) } for (i = 0; mods[i] != NULL; ++i) { - if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) + if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute)) break; } @@ -542,7 +542,7 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state) SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { + if ( strnequal( p, "URL:", 4 ) ) { p += 4; } diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 28466e43f2..6e546bc161 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -45,10 +45,10 @@ void set_local_machine_name(const char* local_name, BOOL perm) * arrggg!!! */ - if (strcasecmp(local_name, "*SMBSERVER")==0) + if (strequal(local_name, "*SMBSERVER")) return; - if (strcasecmp(local_name, "*SMBSERV")==0) + if (strequal(local_name, "*SMBSERV")) return; if (already_perm) diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 5a1f631ba4..eb19caa31b 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -837,8 +837,8 @@ static BOOL matchname(char *remotehost,struct in_addr addr) * DNS is perverted). We always check the address list, though. */ - if (strcasecmp(remotehost, hp->h_name) - && strcasecmp(remotehost, "localhost")) { + if (!strequal(remotehost, hp->h_name) + && !strequal(remotehost, "localhost")) { DEBUG(0,("host name/name mismatch: %s != %s\n", remotehost, hp->h_name)); return False; diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index dd31439d83..9774968e12 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -95,10 +95,10 @@ ADS_STRUCT *ads_init(const char *realm, ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL; /* we need to know if this is a foreign realm */ - if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) { + if (realm && *realm && !strequal(lp_realm(), realm)) { ads->server.foreign = 1; } - if (workgroup && *workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) { + if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) { ads->server.foreign = 1; } diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 8c3185ea5e..b3706cb240 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -972,7 +972,7 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn) **/ char *ads_ou_string(const char *org_unit) { - if (!org_unit || !*org_unit || strcasecmp(org_unit, "Computers") == 0) { + if (!org_unit || !*org_unit || strequal(org_unit, "Computers")) { return strdup("cn=Computers"); } @@ -1970,8 +1970,8 @@ ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **workg prefix_length = strlen(prefix); for (i=0;principles[i]; i++) { - if (strncasecmp(principles[i], prefix, prefix_length) == 0 && - strcasecmp(ads->config.realm, principles[i]+prefix_length) != 0 && + if (strnequal(principles[i], prefix, prefix_length) && + !strequal(ads->config.realm, principles[i]+prefix_length) && !strchr(principles[i]+prefix_length, '.')) { /* found an alternate (short) name for the domain. */ DEBUG(3,("Found alternate name '%s' for realm '%s'\n", diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index a596f00ddb..df7f856cd7 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -34,7 +34,7 @@ static BOOL ads_dc_name(const char *domain, struct in_addr *dc_ip, fstring srv_n ADS_STRUCT *ads; const char *realm = domain; - if (strcasecmp(realm, lp_workgroup()) == 0) + if (strequal(realm, lp_workgroup())) realm = lp_realm(); ads = ads_init(realm, domain, NULL); diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c index f8a97effee..5cc4bf45d6 100644 --- a/source3/msdfs/msdfs.c +++ b/source3/msdfs/msdfs.c @@ -314,7 +314,7 @@ BOOL dfs_redirect(char* pathname, connection_struct* conn, return False; } - if (strcasecmp(dp.servicename, lp_servicename(SNUM(conn)) ) != 0) + if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, @@ -362,7 +362,7 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, parse_dfs_path(pathname, &dp); /* Verify hostname in path */ - if (local_machine && (strcasecmp(local_machine, dp.hostname) != 0)) { + if (local_machine && (!strequal(local_machine, dp.hostname))) { /* Hostname mismatch, check if one of our IP addresses */ if (!ismyip(*interpret_addr2(dp.hostname))) { @@ -711,7 +711,7 @@ BOOL create_junction(char* pathname, struct junction_map* jn) parse_dfs_path(pathname,&dp); /* check if path is dfs : validate first token */ - if (local_machine && (strcasecmp(local_machine,dp.hostname)!=0)) { + if (local_machine && (!strequal(local_machine,dp.hostname))) { /* Hostname mismatch, check if one of our IP addresses */ if (!ismyip(*interpret_addr2(dp.hostname))) { diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c index fabc0eddca..19b00f1f4d 100644 --- a/source3/nmbd/nmbd_elections.c +++ b/source3/nmbd/nmbd_elections.c @@ -247,7 +247,7 @@ static BOOL win_election(struct work_record *work, int version, if (timeup < mytimeup) return(True); - if (strcasecmp(global_myname(), server_name) > 0) + if (StrCaseCmp(global_myname(), server_name) > 0) return(False); return(True); diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 8bd2c66511..ba14a51d24 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -336,7 +336,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); /* Paranoia */ - if (strcasecmp(domain->name, domains[0]) != 0) { + if (!strequal(domain->name, domains[0])) { DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0])); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 850a0b1a2d..6d1675752f 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -92,13 +92,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ for (domain = _domain_list; domain; domain = domain->next) { - if (strcasecmp(domain_name, domain->name) == 0 || - strcasecmp(domain_name, domain->alt_name) == 0) { + if (strequal(domain_name, domain->name) || + strequal(domain_name, domain->alt_name)) { return domain; } if (alternative_name && *alternative_name) { - if (strcasecmp(alternative_name, domain->name) == 0 || - strcasecmp(alternative_name, domain->alt_name) == 0) { + if (strequal(alternative_name, domain->name) || + strequal(alternative_name, domain->alt_name)) { return domain; } } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index e6705d8c7b..bedb57670d 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -2029,7 +2029,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum) } for (i=0; _enum[i].name; i++) { - if (strcasecmp(_enum[i].name,s)==0) + if (strequal(_enum[i].name,s)) return _enum[i].value; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 5cf1691f0d..fdc79ae2ab 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -356,7 +356,7 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, } for (values=ldap_values;*values;values++) { - if (strcasecmp(*values, LDAP_OBJ_POSIXACCOUNT ) == 0) { + if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) { break; } } diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 8cdbec9b9d..562d50f89e 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -431,7 +431,7 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s continue; } - if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { + if (strnequal((char *) p, "NO PASSWORD", 11)) { pw_buf->smb_passwd = NULL; pw_buf->acct_ctrl |= ACB_PWNOTREQ; } else { diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e0efb3e41b..7e7bc8c68c 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -427,7 +427,7 @@ static BOOL is_reserved_name(const char *name) for (i=0; reserved_names[i]; i++) { int len = strlen(reserved_names[i]); /* note that we match on COM1 as well as COM1.foo */ - if (strncasecmp(name, reserved_names[i], len) == 0 && + if (strnequal(name, reserved_names[i], len) && (name[len] == '.' || name[len] == 0)) { return True; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 945855b832..314ffbb4a9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -186,7 +186,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } *p = 0; - if (strcasecmp(p+1, lp_realm()) != 0) { + if (!strequal(p+1, lp_realm())) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c index 6d55c1d9da..0a6deede41 100644 --- a/source3/smbwrapper/smbw_dir.c +++ b/source3/smbwrapper/smbw_dir.c @@ -216,7 +216,7 @@ int smbw_dir_open(const char *fname) smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL, smbw_server_add, NULL); *p = '#'; - } else if ((strcmp(srv->cli.dev,"IPC") == 0) || (strcasecmp(share,"IPC$") == 0)) { + } else if ((strcmp(srv->cli.dev,"IPC") == 0) || (strequal(share,"IPC$"))) { DEBUG(4,("doing NetShareEnum\n")); smbw_share_add(".",0,"", NULL); smbw_share_add("..",0,"", NULL); @@ -413,7 +413,7 @@ int smbw_chdir(const char *name) } if (strncmp(srv->cli.dev,"IPC",3) && - strcasecmp(share, "IPC$") && + !strequal(share, "IPC$") && strncmp(srv->cli.dev,"LPT",3) && !smbw_getatr(srv, path, &mode, NULL, NULL, NULL, NULL, NULL)) { diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index 9a719349b6..f31621b23b 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -85,7 +85,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) data = tdb_fetch_bystring(tdb, shortname); if (data.dptr) { /* maybe its a duplicate long name? */ - if (strcasecmp(name, data.dptr) != 0) { + if (!strequal(name, data.dptr)) { /* we have a collision */ collisions++; printf("Collision between %s and %s -> %s " diff --git a/source3/utils/net.c b/source3/utils/net.c index 42966b4f83..38c144caa8 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -84,14 +84,14 @@ uint32 get_sec_channel_type(const char *param) if (!(param && *param)) { return get_default_sec_channel(); } else { - if (strcasecmp(param, "PDC")==0) { + if (strequal(param, "PDC")) { return SEC_CHAN_BDC; - } else if (strcasecmp(param, "BDC")==0) { + } else if (strequal(param, "BDC")) { return SEC_CHAN_BDC; - } else if (strcasecmp(param, "MEMBER")==0) { + } else if (strequal(param, "MEMBER")) { return SEC_CHAN_WKSTA; #if 0 - } else if (strcasecmp(param, "DOMAIN")==0) { + } else if (strequal(param, "DOMAIN")) { return SEC_CHAN_DOMAIN; #endif } else { diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c index 64321d5bfc..0bd8755420 100644 --- a/source3/utils/smbcquotas.c +++ b/source3/utils/smbcquotas.c @@ -140,7 +140,7 @@ static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA BOOL enable = False; BOOL deny = False; - if (strncasecmp(set_str,"UQLIM:",6)==0) { + if (strnequal(set_str,"UQLIM:",6)) { p += 6; *qtype = SMB_USER_QUOTA_TYPE; *cmd = QUOTA_SETLIM; @@ -154,12 +154,12 @@ static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA fstrcpy(username_str,p); p = p2; - } else if (strncasecmp(set_str,"FSQLIM:",7)==0) { + } else if (strnequal(set_str,"FSQLIM:",7)) { p +=7; *qtype = SMB_USER_FS_QUOTA_TYPE; *cmd = QUOTA_SETLIM; todo = PARSE_LIM; - } else if (strncasecmp(set_str,"FSQFLAGS:",9)==0) { + } else if (strnequal(set_str,"FSQFLAGS:",9)) { p +=9; todo = PARSE_FLAGS; *qtype = SMB_USER_FS_QUOTA_TYPE; @@ -189,13 +189,13 @@ static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA p2++; } - if (strncasecmp(p,"QUOTA_ENABLED",13)==0) { + if (strnequal(p,"QUOTA_ENABLED",13)) { enable = True; - } else if (strncasecmp(p,"DENY_DISK",9)==0) { + } else if (strnequal(p,"DENY_DISK",9)) { deny = True; - } else if (strncasecmp(p,"LOG_SOFTLIMIT",13)==0) { + } else if (strnequal(p,"LOG_SOFTLIMIT",13)) { pqt->qflags |= QUOTAS_LOG_THRESHOLD; - } else if (strncasecmp(p,"LOG_HARDLIMIT",13)==0) { + } else if (strnequal(p,"LOG_HARDLIMIT",13)) { pqt->qflags |= QUOTAS_LOG_LIMIT; } else { return -1; diff --git a/source3/web/cgi.c b/source3/web/cgi.c index 8e739cd224..6778e59656 100644 --- a/source3/web/cgi.c +++ b/source3/web/cgi.c @@ -114,7 +114,7 @@ void cgi_load_variables(void) if (len > 0 && (request_post || ((s=getenv("REQUEST_METHOD")) && - strcasecmp(s,"POST")==0))) { + strequal(s,"POST")))) { while (len && (line=grab_line(f, &len))) { p = strchr_m(line,'='); if (!p) continue; @@ -224,9 +224,9 @@ static void cgi_setup_error(const char *err, const char *header, const char *inf /* damn browsers don't like getting cut off before they give a request */ char line[1024]; while (fgets(line, sizeof(line)-1, stdin)) { - if (strncasecmp(line,"GET ", 4)==0 || - strncasecmp(line,"POST ", 5)==0 || - strncasecmp(line,"PUT ", 4)==0) { + if (strnequal(line,"GET ", 4) || + strnequal(line,"POST ", 5) || + strnequal(line,"PUT ", 4)) { break; } } @@ -301,7 +301,7 @@ static BOOL cgi_handle_authorization(char *line) fstring user, user_pass; struct passwd *pass = NULL; - if (strncasecmp(line,"Basic ", 6)) { + if (!strnequal(line,"Basic ", 6)) { goto err; } line += 6; @@ -489,22 +489,22 @@ void cgi_setup(const char *rootdir, int auth_required) and handle authentication etc */ while (fgets(line, sizeof(line)-1, stdin)) { if (line[0] == '\r' || line[0] == '\n') break; - if (strncasecmp(line,"GET ", 4)==0) { + if (strnequal(line,"GET ", 4)) { got_request = True; url = strdup(&line[4]); - } else if (strncasecmp(line,"POST ", 5)==0) { + } else if (strnequal(line,"POST ", 5)) { got_request = True; request_post = 1; url = strdup(&line[5]); - } else if (strncasecmp(line,"PUT ", 4)==0) { + } else if (strnequal(line,"PUT ", 4)) { got_request = True; cgi_setup_error("400 Bad Request", "", "This server does not accept PUT requests"); - } else if (strncasecmp(line,"Authorization: ", 15)==0) { + } else if (strnequal(line,"Authorization: ", 15)) { authenticated = cgi_handle_authorization(&line[15]); - } else if (strncasecmp(line,"Content-Length: ", 16)==0) { + } else if (strnequal(line,"Content-Length: ", 16)) { content_length = atoi(&line[16]); - } else if (strncasecmp(line,"Accept-Language: ", 17)==0) { + } else if (strnequal(line,"Accept-Language: ", 17)) { web_set_lang(&line[17]); } /* ignore all other requests! */ -- cgit From 0604336c3c985bded8aa20a211b2e62e5439deb7 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Thu, 23 Oct 2003 06:35:45 +0000 Subject: Apply the changes to libsmbclient that derrell has contributed. Fix some of the problems with this. From: Derrell.Lipman@unwireduniverse.com (This used to be commit 8e3d2708c5e5a9968aeb9a6fe6c828aa8a5b22a9) --- source3/Makefile.in | 6 +- source3/include/libsmbclient.h | 864 ++++++++++++++++ source3/libsmb/libsmb_compat.c | 190 +++- source3/libsmb/libsmbclient.c | 2209 ++++++++++++++++++++++++++++++++-------- 4 files changed, 2837 insertions(+), 432 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 10c07d05eb..8c1c65e865 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -472,8 +472,10 @@ SMBWRAPPER_OBJ1 = smbwrapper/wrapped.o SMBWRAPPER_OBJ = $(SMBW_OBJ) $(SMBWRAPPER_OBJ1) LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \ - libsmb/libsmb_cache.o $(PARAM_OBJ) $(LIB_OBJ) \ - $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) + libsmb/libsmb_cache.o \ + $(PARAM_OBJ) $(LIB_OBJ) \ + $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \ + $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) # This shared library is intended for linking with unit test programs # to test Samba internals. It's called libbigballofmud.so to diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index f5d653f697..afcafeed81 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -5,6 +5,7 @@ Copyright (C) Richard Sharpe 2000 Copyright (C) John Terpsra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003 This program is free software; you can redistribute it and/or modify @@ -65,6 +66,9 @@ #include #include #include +#include + +#define SMBC_BASE_FD 10000 /* smallest file descriptor returned */ #define SMBC_WORKGROUP 1 #define SMBC_SERVER 2 @@ -113,6 +117,20 @@ struct smbc_dirent char name[1]; }; +/* + * Flags for smbc_setxattr() + * Specify a bitwise OR of these, or 0 to add or replace as necessary + */ +#define SMBC_XATTR_FLAG_CREATE 0x1 /* fail if attr already exists */ +#define SMBC_XATTR_FLAG_REPLACE 0x2 /* fail if attr does not exist */ + + +#ifndef ENOATTR +# define ENOATTR ENOENT /* No such attribute */ +#endif + + + /**@ingroup structure * Structure that represents a print job. @@ -358,6 +376,27 @@ struct _SMBCCTX { off_t (*telldir) (SMBCCTX *c, SMBCFILE *dir); int (*lseekdir)(SMBCCTX *c, SMBCFILE *dir, off_t offset); int (*fstatdir)(SMBCCTX *c, SMBCFILE *dir, struct stat *st); + int (*chmod)(SMBCCTX *c, const char *fname, mode_t mode); + int (*utimes)(SMBCCTX *c, + const char *fname, struct timeval *tbuf); + int (*setxattr)(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags); + int (*getxattr)(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size); + int (*removexattr)(SMBCCTX *context, + const char *fname, + const char *name); + int (*listxattr)(SMBCCTX *context, + const char *fname, + char *list, + size_t size); /** callable functions for printing */ @@ -499,6 +538,30 @@ SMBCCTX * smbc_init_context(SMBCCTX * context); int smbc_init(smbc_get_auth_data_fn fn, int debug); +/**@ingroup misc + * Set or retrieve the compatibility library's context pointer + * + * @param context New context to use, or NULL. If a new context is provided, + * it must have allocated with smbc_new_context() and + * initialized with smbc_init_context(), followed, optionally, + * by some manual changes to some of the non-internal fields. + * + * @return The old context. + * + * @see smbc_new_context(), smbc_init_context(), smbc_init() + * + * @note This function may be called prior to smbc_init() to force + * use of the next context without any internal calls to + * smbc_new_context() or smbc_init_context(). It may also + * be called after smbc_init() has already called those two + * functions, to replace the existing context with a new one. + * Care should be taken, in this latter case, to ensure that + * the server cache and any data allocated by the + * authentication functions have been freed, if necessary. + */ + +SMBCCTX * smbc_set_context(SMBCCTX * new_context); + /**@ingroup file * Open a file on an SMB server. * @@ -1008,6 +1071,807 @@ int smbc_chown(const char *url, uid_t owner, gid_t group); */ int smbc_chmod(const char *url, mode_t mode); +/**@ingroup attribute + * Change the last modification time on a file + * + * @param url The smb url of the file or directory to change + * the modification time of + * + * @param tbuf A timeval structure which contains the desired + * modification time. NOTE: Only the tv_sec field is + * used. The tv_usec (microseconds) portion is ignored. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - EPERM Permission was denied. + * + */ +int smbc_utimes(const char *url, struct timeval *tbuf); + +#ifdef HAVE_UTIME_H +/**@ingroup attribute + * Change the last modification time on a file + * + * @param url The smb url of the file or directory to change + * the modification time of + * + * @param utbuf A utimebuf structure which contains the desired + * modification time. NOTE: Although the structure contains + * an access time as well, the access time value is ignored. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * + */ +int smbc_utime(const char *fname, struct utimbuf *utbuf); +#endif + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param url The smb url of the file or directory to set extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_setxattr(const char *url, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list). The + * POSIX function which this maps to would act on a symbolic link rather than + * acting on what the symbolic link points to, but with no symbolic links in + * SMB file systems, this function is functionally identical to + * smbc_setxattr(). + * + * @param url The smb url of the file or directory to set extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_lsetxattr(const char *url, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_fsetxattr(int fd, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Get extended attributes for a file. + * + * @param url The smb url of the file or directory to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_getxattr(const char *url, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Get extended attributes for a file. The POSIX function which this maps to + * would act on a symbolic link rather than acting on what the symbolic link + * points to, but with no symbolic links in SMB file systems, this function + * is functionally identical to smbc_getxattr(). + * + * @param url The smb url of the file or directory to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_lgetxattr(const char *url, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Get extended attributes for a file. + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_fgetxattr(int fd, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param url The smb url of the file or directory to remove the extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_removexattr(const char *url, + const char *name); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) The POSIX + * function which this maps to would act on a symbolic link rather than acting + * on what the symbolic link points to, but with no symbolic links in SMB file + * systems, this function is functionally identical to smbc_removexattr(). + * + * @param url The smb url of the file or directory to remove the extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_lremovexattr(const char *url, + const char *name); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_fremovexattr(int fd, + const char *name); + + +/**@ingroup attribute + * List the supported extended attribute names associated with a file + * + * @param url The smb url of the file or directory to list the extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of wether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_listxattr(const char *url, + char *list, + size_t size); + +/**@ingroup attribute + * List the supported extended attribute names associated with a file The + * POSIX function which this maps to would act on a symbolic link rather than + * acting on what the symbolic link points to, but with no symbolic links in + * SMB file systems, this function is functionally identical to + * smbc_listxattr(). + * + * @param url The smb url of the file or directory to list the extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of wether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_llistxattr(const char *url, + char *list, + size_t size); + +/**@ingroup attribute + * List the supported extended attribute names associated with a file + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of wether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_flistxattr(int fd, + char *list, + size_t size); /**@ingroup print * Print a file given the name in fname. It would be a URL ... diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index 27b274953a..4c96c41c56 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -5,6 +5,7 @@ Copyright (C) Richard Sharpe 2000 Copyright (C) John Terpstra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 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 @@ -34,14 +35,14 @@ struct smbc_compat_fdlist { static SMBCCTX * statcont = NULL; static int smbc_compat_initialized = 0; -static int smbc_currentfd = 10000; -static struct smbc_compat_fdlist * smbc_compat_fdlist = NULL; - +static int smbc_compat_nextfd = 0; +static struct smbc_compat_fdlist * smbc_compat_fd_in_use = NULL; +static struct smbc_compat_fdlist * smbc_compat_fd_avail = NULL; /* Find an fd and return the SMBCFILE * or NULL on failure */ static SMBCFILE * find_fd(int fd) { - struct smbc_compat_fdlist * f = smbc_compat_fdlist; + struct smbc_compat_fdlist * f = smbc_compat_fd_in_use; while (f) { if (f->fd == fd) return f->file; @@ -53,16 +54,36 @@ static SMBCFILE * find_fd(int fd) /* Add an fd, returns 0 on success, -1 on error with errno set */ static int add_fd(SMBCFILE * file) { - struct smbc_compat_fdlist * f = malloc(sizeof(struct smbc_compat_fdlist)); - if (!f) { - errno = ENOMEM; - return -1; - } + struct smbc_compat_fdlist * f = smbc_compat_fd_avail; + + if (f) { + /* We found one that's available */ + DLIST_REMOVE(smbc_compat_fd_avail, f); + + } else { + /* + * None were available, so allocate one. Keep the number of + * file descriptors determinate. This allows the application + * to allocate bitmaps or mapping of file descriptors based on + * a known maximum number of file descriptors that will ever + * be returned. + */ + if (smbc_compat_nextfd >= FD_SETSIZE) { + errno = EMFILE; + return -1; + } + + f = malloc(sizeof(struct smbc_compat_fdlist)); + if (!f) { + errno = ENOMEM; + return -1; + } - f->fd = smbc_currentfd++; + f->fd = SMBC_BASE_FD + smbc_compat_nextfd++; + } + f->file = file; - - DLIST_ADD(smbc_compat_fdlist, f); + DLIST_ADD(smbc_compat_fd_in_use, f); return f->fd; } @@ -72,16 +93,19 @@ static int add_fd(SMBCFILE * file) /* Delete an fd, returns 0 on success */ static int del_fd(int fd) { - struct smbc_compat_fdlist * f = smbc_compat_fdlist; + struct smbc_compat_fdlist * f = smbc_compat_fd_in_use; + while (f) { if (f->fd == fd) break; f = f->next; } + if (f) { /* found */ - DLIST_REMOVE(smbc_compat_fdlist, f); - SAFE_FREE(f); + DLIST_REMOVE(smbc_compat_fd_in_use, f); + f->file = NULL; + DLIST_ADD(smbc_compat_fd_avail, f); return 0; } return 1; @@ -91,6 +115,9 @@ static int del_fd(int fd) int smbc_init(smbc_get_auth_data_fn fn, int debug) { + int i; + struct smbc_compat_fdlist * f; + if (!smbc_compat_initialized) { statcont = smbc_new_context(); if (!statcont) @@ -112,6 +139,22 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug) } +SMBCCTX *smbc_set_context(SMBCCTX * context) +{ + SMBCCTX *old_context = statcont; + + if (context) { + /* Save provided context. It must have been initialized! */ + statcont = context; + + /* You'd better know what you're doing. We won't help you. */ + smbc_compat_initialized = 1; + } + + return old_context; +} + + int smbc_open(const char *furl, int flags, mode_t mode) { SMBCFILE * file; @@ -252,8 +295,121 @@ int smbc_fstat(int fd, struct stat *st) int smbc_chmod(const char *url, mode_t mode) { - /* NOT IMPLEMENTED IN LIBSMBCLIENT YET */ - return -1; + return statcont->chmod(statcont, url, mode); +} + +int smbc_utimes(const char *fname, struct timeval *tbuf) +{ + return statcont->utimes(statcont, fname, tbuf); +} + +#ifdef HAVE_UTIME_H +int smbc_utime(const char *fname, struct utimbuf *utbuf) +{ + struct timeval tv; + + if (utbuf == NULL) + return statcont->utimes(statcont, fname, NULL); + + tv.tv_sec = utbuf->modtime; + tv.tv_usec = 0; + return statcont->utimes(statcont, fname, &tv); +} +#endif + +int smbc_setxattr(const char *fname, + const char *name, + const void *value, + size_t size, + int flags) +{ + return statcont->setxattr(statcont, fname, name, value, size, flags); +} + +int smbc_lsetxattr(const char *fname, + const char *name, + const void *value, + size_t size, + int flags) +{ + return statcont->setxattr(statcont, fname, name, value, size, flags); +} + +int smbc_fsetxattr(int fd, + const char *name, + const void *value, + size_t size, + int flags) +{ + SMBCFILE * file = find_fd(fd); + return statcont->setxattr(statcont, file->fname, + name, value, size, flags); +} + +int smbc_getxattr(const char *fname, + const char *name, + const void *value, + size_t size) +{ + return statcont->getxattr(statcont, fname, name, value, size); +} + +int smbc_lgetxattr(const char *fname, + const char *name, + const void *value, + size_t size) +{ + return statcont->getxattr(statcont, fname, name, value, size); +} + +int smbc_fgetxattr(int fd, + const char *name, + const void *value, + size_t size) +{ + SMBCFILE * file = find_fd(fd); + return statcont->getxattr(statcont, file->fname, name, value, size); +} + +int smbc_removexattr(const char *fname, + const char *name) +{ + return statcont->removexattr(statcont, fname, name); +} + +int smbc_lremovexattr(const char *fname, + const char *name) +{ + return statcont->removexattr(statcont, fname, name); +} + +int smbc_fremovexattr(int fd, + const char *name) +{ + SMBCFILE * file = find_fd(fd); + return statcont->removexattr(statcont, file->fname, name); +} + +int smbc_listxattr(const char *fname, + char *list, + size_t size) +{ + return statcont->listxattr(statcont, fname, list, size); +} + +int smbc_llistxattr(const char *fname, + char *list, + size_t size) +{ + return statcont->listxattr(statcont, fname, list, size); +} + +int smbc_flistxattr(int fd, + char *list, + size_t size) +{ + SMBCFILE * file = find_fd(fd); + return statcont->listxattr(statcont, file->fname, list, size); } int smbc_print_file(const char *fname, const char *printq) diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 4eb7f49760..a11a965fde 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -5,6 +5,7 @@ Copyright (C) Richard Sharpe 2000, 2002 Copyright (C) John Terpstra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 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 @@ -25,6 +26,22 @@ #include "../include/libsmb_internal.h" +/* + * Internal flags for extended attributes + */ + +/* internal mode values */ +#define SMBC_XATTR_MODE_ADD 1 +#define SMBC_XATTR_MODE_REMOVE 2 +#define SMBC_XATTR_MODE_REMOVE_ALL 3 +#define SMBC_XATTR_MODE_SET 4 +#define SMBC_XATTR_MODE_CHOWN 5 +#define SMBC_XATTR_MODE_CHGRP 6 + +#define CREATE_ACCESS_READ READ_CONTROL_ACCESS + + + /* * Functions exported by libsmb_cache.c that we need here */ @@ -162,8 +179,9 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, /* see if it has the right prefix */ len = strlen(smbc_prefix); - if (strncmp(s,smbc_prefix,len) || - (s[len] != '/' && s[len] != 0)) return -1; /* What about no smb: ? */ + if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) { + return -1; /* What about no smb: ? */ + } p = s + len; @@ -343,6 +361,67 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv) return 0; } +SMBCSRV *find_server(SMBCCTX *context, + const char *server, + const char *share, + fstring workgroup, + fstring username, + fstring password) +{ + SMBCSRV *srv; + int auth_called = 0; + + check_server_cache: + + srv = context->callbacks.get_cached_srv_fn(context, server, share, + workgroup, username); + + if (!auth_called && !srv && (!username[0] || !password[0])) { + context->callbacks.auth_fn(server, share, + workgroup, sizeof(fstring), + username, sizeof(fstring), + password, sizeof(fstring)); + /* + * However, smbc_auth_fn may have picked up info relating to + * an existing connection, so try for an existing connection + * again ... + */ + auth_called = 1; + goto check_server_cache; + + } + + if (srv) { + if (context->callbacks.check_server_fn(context, srv)) { + /* + * This server is no good anymore + * Try to remove it and check for more possible + * servers in the cache + */ + if (context->callbacks.remove_unused_server_fn(context, + srv)) { + /* + * We could not remove the server completely, + * remove it from the cache so we will not get + * it again. It will be removed when the last + * file/dir is closed. + */ + context->callbacks.remove_cached_srv_fn(context, + srv); + } + + /* + * Maybe there are more cached connections to this + * server + */ + goto check_server_cache; + } + return srv; + } + + return NULL; +} + /* * Connect to a server, possibly on an existing connection * @@ -360,7 +439,6 @@ SMBCSRV *smbc_server(SMBCCTX *context, fstring password) { SMBCSRV *srv=NULL; - int auth_called = 0; struct cli_state c; struct nmb_name called, calling; char *p; @@ -378,45 +456,10 @@ SMBCSRV *smbc_server(SMBCCTX *context, return NULL; } - check_server_cache: - - srv = context->callbacks.get_cached_srv_fn(context, server, share, - workgroup, username); - - if (!auth_called && !srv && (!username[0] || !password[0])) { - context->callbacks.auth_fn(server, share, workgroup, sizeof(fstring), - username, sizeof(fstring), password, sizeof(fstring)); - /* - * However, smbc_auth_fn may have picked up info relating to an - * existing connection, so try for an existing connection again ... - */ - auth_called = 1; - goto check_server_cache; - - } - - if (srv) { - if (context->callbacks.check_server_fn(context, srv)) { - /* - * This server is no good anymore - * Try to remove it and check for more possible servers in the cache - */ - if (context->callbacks.remove_unused_server_fn(context, srv)) { - /* - * We could not remove the server completely, remove it from the cache - * so we will not get it again. It will be removed when the last file/dir - * is closed. - */ - context->callbacks.remove_cached_srv_fn(context, srv); - } - - /* - * Maybe there are more cached connections to this server - */ - goto check_server_cache; - } - return srv; - } + srv = find_server(context, server, share, + workgroup, username, password); + if (srv) + return srv; make_nmb_name(&calling, context->netbios_name, 0x0); make_nmb_name(&called , server, 0x20); @@ -441,16 +484,26 @@ SMBCSRV *smbc_server(SMBCCTX *context, /* have to open a new connection */ if (!cli_initialise(&c)) { - errno = ENOENT; + errno = ENOMEM; return NULL; } c.timeout = context->timeout; + /* Force use of port 139 for first try, so browse lists can work */ + c.port = 139; + if (!cli_connect(&c, server_n, &ip)) { - cli_shutdown(&c); - errno = ENOENT; - return NULL; + /* + * Port 139 connection failed. Try port 445 to handle + * connections to newer (e.g. XP) hosts with NetBIOS disabled. + */ + c.port = 445; + if (!cli_connect(&c, server_n, &ip)) { + cli_shutdown(&c); + errno = ENETUNREACH; + return NULL; + } } if (!cli_session_request(&c, &calling, &called)) { @@ -552,6 +605,101 @@ SMBCSRV *smbc_server(SMBCCTX *context, return NULL; } +/* + * Connect to a server for getting/setting attributes, possibly on an existing + * connection. This works similarly to smbc_server(). + */ +SMBCSRV *smbc_attr_server(SMBCCTX *context, + const char *server, const char *share, + fstring workgroup, + fstring username, fstring password) +{ + struct in_addr ip; + struct cli_state *ipc_cli; + NTSTATUS nt_status; + SMBCSRV *ipc_srv=NULL; + POLICY_HND pol; + + /* + * See if we've already created this special connection. Reference + * our "special" share name 'IPC$$'. + */ + ipc_srv = find_server(context, server, "IPC$$", + workgroup, username, password); + if (!ipc_srv) { + + /* We didn't find a cached connection. Get the password */ + if (*password == '\0') { + /* ... then retrieve it now. */ + context->callbacks.auth_fn(server, share, + workgroup, sizeof(fstring), + username, sizeof(fstring), + password, sizeof(fstring)); + } + + zero_ip(&ip); + nt_status = cli_full_connection(&ipc_cli, + global_myname(), server, + &ip, 0, "IPC$", "?????", + username, workgroup, + password, 0, + Undefined, NULL); + if (! NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("cli_full_connection failed! (%s)\n", + nt_errstr(nt_status))); + errno = ENOTSUP; + return NULL; + } + + if (!cli_nt_session_open(ipc_cli, PI_LSARPC)) { + DEBUG(0, ("cli_nt_session_open fail! (%s)\n", + nt_errstr(nt_status))); + errno = ENOTSUP; + free(ipc_cli); + return NULL; + } + + /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, + but NT sends 0x2000000 so we might as well do it too. */ + + nt_status = cli_lsa_open_policy(ipc_cli, + ipc_cli->mem_ctx, + True, + GENERIC_EXECUTE_ACCESS, + &pol); + + if (!NT_STATUS_IS_OK(nt_status)) { + errno = smbc_errno(context, ipc_cli); + free(ipc_cli); + return NULL; + } + + ipc_srv = (SMBCSRV *)malloc(sizeof(*ipc_srv)); + if (!ipc_srv) { + errno = ENOMEM; + free(ipc_cli); + return NULL; + } + + ZERO_STRUCTP(ipc_srv); + ipc_srv->cli = *ipc_cli; + + free(ipc_cli); + + /* now add it to the cache (internal or external) */ + if (context->callbacks.add_cached_srv_fn(context, ipc_srv, + server, + "IPC$$", + workgroup, + username)) { + DEBUG(3, (" Failed to add server to cache\n")); + return NULL; + } + } + + return ipc_srv; +} + /* * Routine to open() a file ... */ @@ -850,7 +998,10 @@ static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path, size, mode, ino)) return True; /* if this is NT then don't bother with the getatr */ - if (srv->cli.capabilities & CAP_NT_SMBS) return False; + if (srv->cli.capabilities & CAP_NT_SMBS) { + errno = EPERM; + return False; + } if (cli_getatr(&srv->cli, path, mode, size, m_time)) { a_time = c_time = m_time; @@ -858,6 +1009,7 @@ static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path, return True; } + errno = EPERM; return False; } @@ -1202,9 +1354,7 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st) srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { - return -1; /* errno set by smbc_server */ - } /* if (strncmp(srv->cli.dev, "IPC", 3) == 0) { @@ -1584,18 +1734,17 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) /* * Get a connection to IPC$ on the server if we do not already have one */ - + srv = smbc_server(context, server, "IPC$", workgroup, user, password); - - if (!srv) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - return NULL; - } - + if (!srv) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + return NULL; + } + dir->srv = srv; dir->dir_type = SMBC_WORKGROUP; @@ -2290,488 +2439,1722 @@ static int smbc_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st) } -/* - * Open a print file to be written to by other calls - */ - -static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname) +int smbc_chmod_ctx(SMBCCTX *context, const char *fname, mode_t newmode) { - fstring server, share, user, password; + SMBCSRV *srv; + fstring server, share, user, password, workgroup; pstring path; - + uint16 mode; + if (!context || !context->internal || !context->internal->_initialized) { - errno = EINVAL; - return NULL; + errno = EINVAL; /* Best I can think of ... */ + return -1; } if (!fname) { errno = EINVAL; - return NULL; + return -1; } - DEBUG(4, ("smbc_open_print_job_ctx(%s)\n", fname)); + DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode)); smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ - /* What if the path is empty, or the file exists? */ - - return context->open(context, fname, O_WRONLY, 666); - -} - -/* - * Routine to print a file on a remote server ... - * - * We open the file, which we assume to be on a remote server, and then - * copy it to a print file on the share specified by printq. - */ - -static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_print, const char *printq) -{ - SMBCFILE *fid1, *fid2; - int bytes, saverr, tot_bytes = 0; - char buf[4096]; - - if (!c_file || !c_file->internal->_initialized || !c_print || - !c_print->internal->_initialized) { - - errno = EINVAL; - return -1; - - } - - if (!fname && !printq) { - - errno = EINVAL; - return -1; - - } - - /* Try to open the file for reading ... */ - - if ((int)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) { - - DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno)); - return -1; /* smbc_open sets errno */ - - } - - /* Now, try to open the printer file for writing */ - - if ((int)(fid2 = c_print->open_print_job(c_print, printq)) < 0) { - - saverr = errno; /* Save errno */ - c_file->close(c_file, fid1); - errno = saverr; - return -1; - - } - - while ((bytes = c_file->read(c_file, fid1, buf, sizeof(buf))) > 0) { - - tot_bytes += bytes; - - if ((c_print->write(c_print, fid2, buf, bytes)) < 0) { + if (user[0] == (char)0) fstrcpy(user, context->user); - saverr = errno; - c_file->close(c_file, fid1); - c_print->close(c_print, fid2); - errno = saverr; + fstrcpy(workgroup, context->workgroup); - } + srv = smbc_server(context, server, share, workgroup, user, password); + if (!srv) { + return -1; /* errno set by smbc_server */ } - saverr = errno; + mode = 0; - c_file->close(c_file, fid1); /* We have to close these anyway */ - c_print->close(c_print, fid2); + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; + if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; + if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; + if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - if (bytes < 0) { - - errno = saverr; + if (!cli_setatr(&srv->cli, path, mode, 0)) { + errno = smbc_errno(context, &srv->cli); return -1; - } - - return tot_bytes; - + + return 0; } -/* - * Routine to list print jobs on a printer share ... - */ - -static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_list_print_job_fn fn) +int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf) { - SMBCSRV *srv; + SMBCSRV *srv; fstring server, share, user, password, workgroup; pstring path; + uint16 mode; + time_t t = (tbuf == NULL ? time(NULL) : tbuf->tv_sec); if (!context || !context->internal || !context->internal->_initialized) { - errno = EINVAL; + errno = EINVAL; /* Best I can think of ... */ return -1; - + } if (!fname) { - + errno = EINVAL; return -1; } - DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname)); + DEBUG(4, ("smbc_utimes(%s, [%s])\n", fname, ctime(&t))); smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ if (user[0] == (char)0) fstrcpy(user, context->user); - + fstrcpy(workgroup, context->workgroup); srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { - return -1; /* errno set by smbc_server */ - } - if (cli_print_queue(&srv->cli, (void (*)(struct print_job_info *))fn) < 0) { - - errno = smbc_errno(context, &srv->cli); - return -1; + if (!smbc_getatr(context, srv, path, + &mode, NULL, + NULL, NULL, NULL, + NULL)) { + return -1; + } + if (!cli_setatr(&srv->cli, path, mode, t)) { + /* some servers always refuse directory changes */ + if (!(mode & aDIR)) { + errno = smbc_errno(context, &srv->cli); + return -1; + } } - - return 0; + return 0; } -/* - * Delete a print job from a remote printer share - */ - -static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id) -{ - SMBCSRV *srv; - fstring server, share, user, password, workgroup; - pstring path; - int err; - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - return -1; +/* The MSDN is contradictory over the ordering of ACE entries in an ACL. + However NT4 gives a "The information may have been modified by a + computer running Windows NT 5.0" if denied ACEs do not appear before + allowed ACEs. */ - } +static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2) +{ + if (sec_ace_equal(ace1, ace2)) + return 0; - if (!fname) { + if (ace1->type != ace2->type) + return ace2->type - ace1->type; - errno = EINVAL; - return -1; + if (sid_compare(&ace1->trustee, &ace2->trustee)) + return sid_compare(&ace1->trustee, &ace2->trustee); - } - - DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname)); + if (ace1->flags != ace2->flags) + return ace1->flags - ace2->flags; - smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + if (ace1->info.mask != ace2->info.mask) + return ace1->info.mask - ace2->info.mask; - if (user[0] == (char)0) fstrcpy(user, context->user); + if (ace1->size != ace2->size) + return ace1->size - ace2->size; - fstrcpy(workgroup, context->workgroup); + return memcmp(ace1, ace2, sizeof(SEC_ACE)); +} - srv = smbc_server(context, server, share, workgroup, user, password); - if (!srv) { +static void sort_acl(SEC_ACL *the_acl) +{ + uint32 i; + if (!the_acl) return; - return -1; /* errno set by smbc_server */ + qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), QSORT_CAST ace_compare); + for (i=1;inum_aces;) { + if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) { + int j; + for (j=i; jnum_aces-1; j++) { + the_acl->ace[j] = the_acl->ace[j+1]; + } + the_acl->num_aces--; + } else { + i++; + } } +} - if ((err = cli_printjob_del(&srv->cli, id)) != 0) { +/* convert a SID to a string, either numeric or username/group */ +static void convert_sid_to_string(struct cli_state *ipc_cli, + POLICY_HND *pol, + fstring str, + BOOL numeric, + DOM_SID *sid) +{ + char **domains = NULL; + char **names = NULL; + uint32 *types = NULL; - if (err < 0) - errno = smbc_errno(context, &srv->cli); - else if (err == ERRnosuchprintjob) - errno = EINVAL; - return -1; + sid_to_string(str, sid); + if (numeric) return; /* no lookup desired */ + + /* Ask LSA to convert the sid to a name */ + + if (!NT_STATUS_IS_OK(cli_lsa_lookup_sids(ipc_cli, ipc_cli->mem_ctx, + pol, 1, sid, &domains, + &names, &types)) || + !domains || !domains[0] || !names || !names[0]) { + return; } - return 0; + /* Converted OK */ + slprintf(str, sizeof(fstring) - 1, "%s%s%s", + domains[0], lp_winbind_separator(), + names[0]); } -/* - * Get a new empty handle to fill in with your own info - */ -SMBCCTX * smbc_new_context(void) +/* convert a string to a SID, either numeric or username/group */ +static BOOL convert_string_to_sid(struct cli_state *ipc_cli, + POLICY_HND *pol, + BOOL numeric, + DOM_SID *sid, + const char *str) { - SMBCCTX * context; + uint32 *types = NULL; + DOM_SID *sids = NULL; + BOOL result = True; - context = malloc(sizeof(SMBCCTX)); - if (!context) { - errno = ENOMEM; - return NULL; - } + if (numeric) { + if (strncmp(str, "S-", 2) == 0) { + return string_to_sid(sid, str); + } - ZERO_STRUCTP(context); + result = False; + goto done; + } - context->internal = malloc(sizeof(struct smbc_internal_data)); - if (!context->internal) { - errno = ENOMEM; - return NULL; + if (!NT_STATUS_IS_OK(cli_lsa_lookup_names(ipc_cli, ipc_cli->mem_ctx, + pol, 1, &str, &sids, + &types))) { + result = False; + goto done; } - ZERO_STRUCTP(context->internal); + sid_copy(sid, &sids[0]); + done: - - /* ADD REASONABLE DEFAULTS */ - context->debug = 0; - context->timeout = 20000; /* 20 seconds */ - - context->open = smbc_open_ctx; - context->creat = smbc_creat_ctx; - context->read = smbc_read_ctx; - context->write = smbc_write_ctx; - context->close = smbc_close_ctx; - context->unlink = smbc_unlink_ctx; - context->rename = smbc_rename_ctx; - context->lseek = smbc_lseek_ctx; - context->stat = smbc_stat_ctx; - context->fstat = smbc_fstat_ctx; - context->opendir = smbc_opendir_ctx; - context->closedir = smbc_closedir_ctx; - context->readdir = smbc_readdir_ctx; - context->getdents = smbc_getdents_ctx; - context->mkdir = smbc_mkdir_ctx; - context->rmdir = smbc_rmdir_ctx; - context->telldir = smbc_telldir_ctx; - context->lseekdir = smbc_lseekdir_ctx; - context->fstatdir = smbc_fstatdir_ctx; - context->open_print_job = smbc_open_print_job_ctx; - context->print_file = smbc_print_file_ctx; - context->list_print_jobs = smbc_list_print_jobs_ctx; - context->unlink_print_job = smbc_unlink_print_job_ctx; - - context->callbacks.check_server_fn = smbc_check_server; - context->callbacks.remove_unused_server_fn = smbc_remove_unused_server; - - smbc_default_cache_functions(context); - - return context; + return result; } -/* - * Free a context - * - * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed - * and thus you'll be leaking memory if not handled properly. - * - */ -int smbc_free_context(SMBCCTX * context, int shutdown_ctx) + +/* parse an ACE in the same format as print_ace() */ +static BOOL parse_ace(struct cli_state *ipc_cli, + POLICY_HND *pol, + SEC_ACE *ace, + BOOL numeric, + char *str) { - if (!context) { - errno = EBADF; - return 1; + char *p; + const char *cp; + fstring tok; + unsigned atype, aflags, amask; + DOM_SID sid; + SEC_ACCESS mask; + const struct perm_value *v; + struct perm_value { + const char *perm; + uint32 mask; + }; + + /* These values discovered by inspection */ + static const struct perm_value special_values[] = { + { "R", 0x00120089 }, + { "W", 0x00120116 }, + { "X", 0x001200a0 }, + { "D", 0x00010000 }, + { "P", 0x00040000 }, + { "O", 0x00080000 }, + { NULL, 0 }, + }; + + static const struct perm_value standard_values[] = { + { "READ", 0x001200a9 }, + { "CHANGE", 0x001301bf }, + { "FULL", 0x001f01ff }, + { NULL, 0 }, + }; + + + ZERO_STRUCTP(ace); + p = strchr_m(str,':'); + if (!p) return False; + *p = '\0'; + p++; + /* Try to parse numeric form */ + + if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && + convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { + goto done; + } + + /* Try to parse text form */ + + if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { + return False; + } + + cp = p; + if (!next_token(&cp, tok, "/", sizeof(fstring))) { + return False; + } + + if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { + atype = SEC_ACE_TYPE_ACCESS_ALLOWED; + } else if (StrnCaseCmp(tok, "DENIED", strlen("DENIED")) == 0) { + atype = SEC_ACE_TYPE_ACCESS_DENIED; + } else { + return False; } - - if (shutdown_ctx) { - SMBCFILE * f; - DEBUG(1,("Performing aggressive shutdown.\n")); - - f = context->internal->_files; - while (f) { - context->close(context, f); - f = f->next; - } - context->internal->_files = NULL; - - /* First try to remove the servers the nice way. */ - if (context->callbacks.purge_cached_fn(context)) { - SMBCSRV * s; - DEBUG(1, ("Could not purge all servers, Nice way shutdown failed.\n")); - s = context->internal->_servers; - while (s) { - cli_shutdown(&s->cli); - context->callbacks.remove_cached_srv_fn(context, s); - SAFE_FREE(s); - s = s->next; - } - context->internal->_servers = NULL; + + /* Only numeric form accepted for flags at present */ + + if (!(next_token(&cp, tok, "/", sizeof(fstring)) && + sscanf(tok, "%i", &aflags))) { + return False; + } + + if (!next_token(&cp, tok, "/", sizeof(fstring))) { + return False; + } + + if (strncmp(tok, "0x", 2) == 0) { + if (sscanf(tok, "%i", &amask) != 1) { + return False; } + goto done; } - else { - /* This is the polite way */ - if (context->callbacks.purge_cached_fn(context)) { - DEBUG(1, ("Could not purge all servers, free_context failed.\n")); - errno = EBUSY; - return 1; + + for (v = standard_values; v->perm; v++) { + if (strcmp(tok, v->perm) == 0) { + amask = v->mask; + goto done; } - if (context->internal->_servers) { - DEBUG(1, ("Active servers in context, free_context failed.\n")); - errno = EBUSY; - return 1; + } + + p = tok; + + while(*p) { + BOOL found = False; + + for (v = special_values; v->perm; v++) { + if (v->perm[0] == *p) { + amask |= v->mask; + found = True; + } } - if (context->internal->_files) { - DEBUG(1, ("Active files in context, free_context failed.\n")); - errno = EBUSY; - return 1; - } + + if (!found) return False; + p++; } - /* Things we have to clean up */ - SAFE_FREE(context->workgroup); - SAFE_FREE(context->netbios_name); - SAFE_FREE(context->user); - - DEBUG(3, ("Context %p succesfully freed\n", context)); - SAFE_FREE(context->internal); - SAFE_FREE(context); - return 0; -} + if (*p) { + return False; + } + done: + mask.mask = amask; + init_sec_ace(ace, &sid, atype, mask, aflags); + return True; +} -/* - * Initialise the library etc - * - * We accept a struct containing handle information. - * valid values for info->debug from 0 to 100, - * and insist that info->fn must be non-null. - */ -SMBCCTX * smbc_init_context(SMBCCTX * context) +/* add an ACE to a list of ACEs in a SEC_ACL */ +static BOOL add_ace(SEC_ACL **the_acl, SEC_ACE *ace, TALLOC_CTX *ctx) { - pstring conf; - int pid; - char *user = NULL, *home = NULL; + SEC_ACL *new; + SEC_ACE *aces; + if (! *the_acl) { + (*the_acl) = make_sec_acl(ctx, 3, 1, ace); + return True; + } - if (!context || !context->internal) { - errno = EBADF; + aces = calloc(1+(*the_acl)->num_aces,sizeof(SEC_ACE)); + memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE)); + memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE)); + new = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces); + SAFE_FREE(aces); + (*the_acl) = new; + return True; +} + + +/* parse a ascii version of a security descriptor */ +static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, + struct cli_state *ipc_cli, + POLICY_HND *pol, + BOOL numeric, + char *str) +{ + const char *p = str; + fstring tok; + SEC_DESC *ret; + size_t sd_size; + DOM_SID *grp_sid=NULL, *owner_sid=NULL; + SEC_ACL *dacl=NULL; + int revision=1; + + while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) { + + if (StrnCaseCmp(tok,"REVISION:", 9) == 0) { + revision = strtol(tok+9, NULL, 16); + continue; + } + + if (StrnCaseCmp(tok,"OWNER:", 6) == 0) { + owner_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (!owner_sid || + !convert_string_to_sid(ipc_cli, pol, + numeric, + owner_sid, tok+6)) { + DEBUG(5, ("Failed to parse owner sid\n")); + return NULL; + } + continue; + } + + if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) { + owner_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (!owner_sid || + !convert_string_to_sid(ipc_cli, pol, + False, + owner_sid, tok+7)) { + DEBUG(5, ("Failed to parse owner sid\n")); + return NULL; + } + continue; + } + + if (StrnCaseCmp(tok,"GROUP:", 6) == 0) { + grp_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (!grp_sid || + !convert_string_to_sid(ipc_cli, pol, + numeric, + grp_sid, tok+6)) { + DEBUG(5, ("Failed to parse group sid\n")); + return NULL; + } + continue; + } + + if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) { + grp_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (!grp_sid || + !convert_string_to_sid(ipc_cli, pol, + False, + grp_sid, tok+6)) { + DEBUG(5, ("Failed to parse group sid\n")); + return NULL; + } + continue; + } + + if (StrnCaseCmp(tok,"ACL:", 4) == 0) { + SEC_ACE ace; + if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) { + DEBUG(5, ("Failed to parse ACL %s\n", tok)); + return NULL; + } + if(!add_ace(&dacl, &ace, ctx)) { + DEBUG(5, ("Failed to add ACL %s\n", tok)); + return NULL; + } + continue; + } + + if (StrnCaseCmp(tok,"ACL+:", 5) == 0) { + SEC_ACE ace; + if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) { + DEBUG(5, ("Failed to parse ACL %s\n", tok)); + return NULL; + } + if(!add_ace(&dacl, &ace, ctx)) { + DEBUG(5, ("Failed to add ACL %s\n", tok)); + return NULL; + } + continue; + } + + DEBUG(5, ("Failed to parse security descriptor\n")); return NULL; } - /* Do not initialise the same client twice */ - if (context->internal->_initialized) { - return 0; - } + ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE, + owner_sid, grp_sid, NULL, dacl, &sd_size); - if (!context->callbacks.auth_fn || context->debug < 0 || context->debug > 100) { + SAFE_FREE(grp_sid); + SAFE_FREE(owner_sid); - errno = EINVAL; - return NULL; + return ret; +} + +/***************************************************** +retrieve the acls for a file +*******************************************************/ +static int cacl_get(TALLOC_CTX *ctx, struct cli_state *cli, + struct cli_state *ipc_cli, POLICY_HND *pol, + char *filename, char *name, char *buf, int bufsize) +{ + uint32 i; + int n = 0; + int n_used; + BOOL all; + BOOL numeric = True; + BOOL determine_size = (bufsize == 0); + int fnum = -1; + SEC_DESC *sd; + fstring sidstr; + char *p; + + fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); + + if (fnum == -1) { + DEBUG(5, ("cacl_get failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; } - if (!smbc_initialized) { - /* Do some library wide intialisations the first time we get called */ + sd = cli_query_secdesc(cli, fnum, ctx); - /* Set this to what the user wants */ - DEBUGLEVEL = context->debug; - - setup_logging( "libsmbclient", True); + if (!sd) { + DEBUG(5, ("cacl_get Failed to query old descriptor\n")); + errno = 0; + return -1; + } - /* Here we would open the smb.conf file if needed ... */ - - home = getenv("HOME"); + cli_close(cli, fnum); + + all = (*name == '*'); + numeric = (* (name + strlen(name) - 1) != '+'); + + n_used = 0; + + if (all) { + if (determine_size) { + p = talloc_asprintf(ctx, + "REVISION:%d", sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "REVISION:%d", sd->revision); + } + } else if (StrCaseCmp(name, "revision") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%d", sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%d", sd->revision); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; - slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home); - - load_interfaces(); /* Load the list of interfaces ... */ - - in_client = True; /* FIXME, make a param */ + /* Get owner and group sid */ - if (!lp_load(conf, True, False, False)) { + if (sd->owner_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, sd->owner_sid); + } else { + fstrcpy(sidstr, ""); + } + + if (all) { + if (determine_size) { + p = talloc_asprintf(ctx, ",OWNER:%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, ",OWNER:%s", sidstr); + } + } else if (StrnCaseCmp(name, "owner", 5) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%s", sidstr); + } + } - /* - * Well, if that failed, try the dyn_CONFIGFILE - * Which points to the standard locn, and if that - * fails, silently ignore it and use the internal - * defaults ... - */ - - if (!lp_load(dyn_CONFIGFILE, True, False, False)) { - DEBUG(5, ("Could not load either config file: %s or %s\n", - conf, dyn_CONFIGFILE)); - } - } + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; - reopen_logs(); /* Get logging working ... */ - - /* - * Block SIGPIPE (from lib/util_sock.c: write()) - * It is not needed and should not stop execution - */ - BlockSignals(True, SIGPIPE); - - /* Done with one-time initialisation */ - smbc_initialized = 1; + if (sd->grp_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, sd->grp_sid); + } else { + fstrcpy(sidstr, ""); + } + + if (all) { + if (determine_size) { + p = talloc_asprintf(ctx, ",GROUP:%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, ",GROUP:%s", sidstr); + } + } else if (StrnCaseCmp(name, "group", 5) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%s", sidstr); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + + /* Add aces to value buffer */ + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + + SEC_ACE *ace = &sd->dacl->ace[i]; + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, &ace->trustee); + + if (all) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",ACL:%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",ACL:%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + } + } else if ((StrnCaseCmp(name, "acl", 3) == 0 && + StrCaseCmp(name + 3, sidstr) == 0) || + (StrnCaseCmp(name, "acl+", 4) == 0 && + StrCaseCmp(name + 4, sidstr) == 0)) { + if (determine_size) { + p = talloc_asprintf(ctx, + "%d/%d/0x%08x", + ace->type, + ace->flags, + ace->info.mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%d/%d/0x%08x", + ace->type, ace->flags, ace->info.mask); + } + } + if (n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + } + + if (n_used == 0) { + errno = ENOATTR; + return -1; + } + return n_used; +} + + +/***************************************************** +set the ACLs on a file given an ascii description +*******************************************************/ +static int cacl_set(TALLOC_CTX *ctx, struct cli_state *cli, + struct cli_state *ipc_cli, POLICY_HND *pol, + const char *filename, const char *the_acl, + int mode, int flags) +{ + int fnum; + int err = 0; + SEC_DESC *sd = NULL, *old; + SEC_ACL *dacl = NULL; + DOM_SID *owner_sid = NULL; + DOM_SID *grp_sid = NULL; + uint32 i, j; + size_t sd_size; + int ret = 0; + char *p; + BOOL numeric = True; + + /* the_acl will be null for REMOVE_ALL operations */ + if (the_acl) { + numeric = ((p = strchr(the_acl, ':')) != NULL && + p > the_acl && + p[-1] != '+'); + + /* if this is to set the entire ACL... */ + if (*the_acl == '*') { + /* ... then increment past the first colon */ + the_acl = p + 1; + } + + sd = sec_desc_parse(ctx, ipc_cli, pol, + numeric, (char *) the_acl); + + if (!sd) { + errno = EINVAL; + return -1; + } + } + + /* The desired access below is the only one I could find that works + with NT4, W2KP and Samba */ + + fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); + if (fnum == -1) { + DEBUG(5, ("cacl_set failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; } - - if (!context->user) { - /* - * FIXME: Is this the best way to get the user info? - */ - user = getenv("USER"); - /* walk around as "guest" if no username can be found */ - if (!user) context->user = strdup("guest"); - else context->user = strdup(user); + + old = cli_query_secdesc(cli, fnum, ctx); + + if (!old) { + DEBUG(5, ("cacl_set Failed to query old descriptor\n")); + errno = 0; + return -1; } - if (!context->netbios_name) { - /* - * We try to get our netbios name from the config. If that fails we fall - * back on constructing our netbios name from our hostname etc - */ - if (global_myname()) { - context->netbios_name = strdup(global_myname()); + cli_close(cli, fnum); + + switch (mode) { + case SMBC_XATTR_MODE_REMOVE_ALL: + old->dacl->num_aces = 0; + SAFE_FREE(old->dacl->ace); + SAFE_FREE(old->dacl); + old->off_dacl = 0; + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_REMOVE: + for (i=0;sd->dacl && idacl->num_aces;i++) { + BOOL found = False; + + for (j=0;old->dacl && jdacl->num_aces;j++) { + if (sec_ace_equal(&sd->dacl->ace[i], + &old->dacl->ace[j])) { + uint32 k; + for (k=j; kdacl->num_aces-1;k++) { + old->dacl->ace[k] = old->dacl->ace[k+1]; + } + old->dacl->num_aces--; + if (old->dacl->num_aces == 0) { + SAFE_FREE(old->dacl->ace); + SAFE_FREE(old->dacl); + old->off_dacl = 0; + } + found = True; + dacl = old->dacl; + break; + } + } + + if (!found) { + err = ENOATTR; + ret = -1; + goto failed; + } } - else { - /* - * Hmmm, I want to get hostname as well, but I am too lazy for the moment - */ - pid = sys_getpid(); - context->netbios_name = malloc(17); - if (!context->netbios_name) { - errno = ENOMEM; - return NULL; + break; + + case SMBC_XATTR_MODE_ADD: + for (i=0;sd->dacl && idacl->num_aces;i++) { + BOOL found = False; + + for (j=0;old->dacl && jdacl->num_aces;j++) { + if (sid_equal(&sd->dacl->ace[i].trustee, + &old->dacl->ace[j].trustee)) { + if (!(flags & SMBC_XATTR_FLAG_CREATE)) { + err = EEXIST; + ret = -1; + goto failed; + } + old->dacl->ace[j] = sd->dacl->ace[i]; + ret = -1; + found = True; + } + } + + if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) { + err = ENOATTR; + ret = -1; + goto failed; } - slprintf(context->netbios_name, 16, "smbc%s%d", context->user, pid); + + for (i=0;sd->dacl && idacl->num_aces;i++) { + add_ace(&old->dacl, &sd->dacl->ace[i], ctx); + } } + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_SET: + old = sd; + owner_sid = old->owner_sid; + grp_sid = old->grp_sid; + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_CHOWN: + owner_sid = sd->owner_sid; + break; + + case SMBC_XATTR_MODE_CHGRP: + grp_sid = sd->grp_sid; + break; } - DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); + /* Denied ACE entries must come before allowed ones */ + sort_acl(old->dacl); - if (!context->workgroup) { - if (lp_workgroup()) { - context->workgroup = strdup(lp_workgroup()); - } - else { - /* TODO: Think about a decent default workgroup */ - context->workgroup = strdup("samba"); - } + /* Create new security descriptor and set it */ + sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE, + owner_sid, grp_sid, NULL, dacl, &sd_size); + + fnum = cli_nt_create(cli, filename, + WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); + + if (fnum == -1) { + DEBUG(5, ("cacl_set failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; } - DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); - - /* shortest timeout is 1 second */ - if (context->timeout > 0 && context->timeout < 1000) - context->timeout = 1000; + if (!cli_set_secdesc(cli, fnum, sd)) { + DEBUG(5, ("ERROR: secdesc set failed: %s\n", cli_errstr(cli))); + ret = -1; + } - /* - * FIXME: Should we check the function pointers here? - */ + /* Clean up */ - context->internal->_initialized = 1; - - return context; + failed: + cli_close(cli, fnum); + + if (err != 0) { + errno = err; + } + + return ret; +} + + +int smbc_setxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags) +{ + int ret; + SMBCSRV *srv; + SMBCSRV *ipc_srv; + fstring server, share, user, password, workgroup; + pstring path; + TALLOC_CTX *ctx; + POLICY_HND pol; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; /* Best I can think of ... */ + return -1; + + } + + if (!fname) { + + errno = EINVAL; + return -1; + + } + + DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n", + fname, name, (int) size, (char *) value)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + if (user[0] == (char)0) fstrcpy(user, context->user); + + fstrcpy(workgroup, context->workgroup); + + srv = smbc_server(context, server, share, workgroup, user, password); + if (!srv) { + return -1; /* errno set by smbc_server */ + } + + ipc_srv = smbc_attr_server(context, server, share, + workgroup, user, password); + if (!ipc_srv) { + return -1; + } + + ctx = talloc_init("smbc_setxattr"); + if (!ctx) { + errno = ENOMEM; + return -1; + } + + /* + * Are they asking to set an access control element or to set + * the entire access control list? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(ctx, "%s:%s", name+19, (char *) value); + if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(ctx, &srv->cli, + &ipc_srv->cli, &pol, path, + namevalue, + (*namevalue == '*' + ? SMBC_XATTR_MODE_SET + : SMBC_XATTR_MODE_ADD), + flags); + } + talloc_destroy(ctx); + return ret; + } + + /* + * Are they asking to set the owner? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(ctx, "%s:%s", name+19, (char *) value); + if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(ctx, &srv->cli, + &ipc_srv->cli, &pol, path, + namevalue, SMBC_XATTR_MODE_CHOWN, 0); + } + talloc_destroy(ctx); + return ret; + } + + /* + * Are they asking to set the group? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(ctx, "%s:%s", name+19, (char *) value); + if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(ctx, &srv->cli, + &ipc_srv->cli, &pol, path, + namevalue, SMBC_XATTR_MODE_CHOWN, 0); + } + talloc_destroy(ctx); + return ret; + } + + /* Unsupported attribute name */ + talloc_destroy(ctx); + errno = EINVAL; + return -1; +} + +int smbc_getxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size) +{ + int ret; + SMBCSRV *srv; + SMBCSRV *ipc_srv; + fstring server, share, user, password, workgroup; + pstring path; + TALLOC_CTX *ctx; + POLICY_HND pol; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; /* Best I can think of ... */ + return -1; + + } + + if (!fname) { + + errno = EINVAL; + return -1; + + } + + DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + if (user[0] == (char)0) fstrcpy(user, context->user); + + fstrcpy(workgroup, context->workgroup); + + srv = smbc_server(context, server, share, workgroup, user, password); + if (!srv) { + return -1; /* errno set by smbc_server */ + } + + ipc_srv = smbc_attr_server(context, server, share, + workgroup, user, password); + if (!ipc_srv) { + return -1; + } + + ctx = talloc_init("smbc:getxattr"); + if (!ctx) { + errno = ENOMEM; + return -1; + } + + /* Are they requesting a supported attribute? */ + if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { + + /* Yup. */ + ret = cacl_get(ctx, &srv->cli, + &ipc_srv->cli, &pol, + (char *) path, (char *) name + 19, + (char *) value, size); + if (ret < 0 && errno == 0) { + errno = smbc_errno(context, &srv->cli); + } + talloc_destroy(ctx); + return ret; + } + + /* Unsupported attribute name */ + talloc_destroy(ctx); + errno = EINVAL; + return -1; +} + + +int smbc_removexattr_ctx(SMBCCTX *context, + const char *fname, + const char *name) +{ + int ret; + SMBCSRV *srv; + SMBCSRV *ipc_srv; + fstring server, share, user, password, workgroup; + pstring path; + TALLOC_CTX *ctx; + POLICY_HND pol; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; /* Best I can think of ... */ + return -1; + + } + + if (!fname) { + + errno = EINVAL; + return -1; + + } + + DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + if (user[0] == (char)0) fstrcpy(user, context->user); + + fstrcpy(workgroup, context->workgroup); + + srv = smbc_server(context, server, share, workgroup, user, password); + if (!srv) { + return -1; /* errno set by smbc_server */ + } + + ipc_srv = smbc_attr_server(context, server, share, + workgroup, user, password); + if (!ipc_srv) { + return -1; + } + + ipc_srv = smbc_attr_server(context, server, share, + workgroup, user, password); + if (!ipc_srv) { + return -1; + } + + ctx = talloc_init("smbc_removexattr"); + if (!ctx) { + errno = ENOMEM; + return -1; + } + + /* Are they asking to set the entire ACL? */ + if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) { + + /* Yup. */ + ret = cacl_set(ctx, &srv->cli, + &ipc_srv->cli, &pol, path, + NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0); + talloc_destroy(ctx); + return ret; + } + + /* + * Are they asking to remove one or more spceific security descriptor + * attributes? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { + + /* Yup. */ + ret = cacl_set(ctx, &srv->cli, + &ipc_srv->cli, &pol, path, + name + 19, SMBC_XATTR_MODE_REMOVE, 0); + talloc_destroy(ctx); + return ret; + } + + /* Unsupported attribute name */ + talloc_destroy(ctx); + errno = EINVAL; + return -1; +} + +int smbc_listxattr_ctx(SMBCCTX *context, + const char *fname, + char *list, + size_t size) +{ + /* + * This isn't quite what listxattr() is supposed to do. This returns + * the complete set of attributes, always, rather than only those + * attribute names which actually exist for a file. Hmmm... + */ + const char supported[] = + "system.nt_sec_desc.revision\0" + "system.nt_sec_desc.owner\0" + "system.nt_sec_desc.owner+\0" + "system.nt_sec_desc.group\0" + "system.nt_sec_desc.group+\0" + "system.nt_sec_desc.acl\0" + "system.nt_sec_desc.acl+\0" + "system.nt_sec_desc.*\0" + "system.nt_sec_desc.*+\0" + ; + + if (size == 0) { + return sizeof(supported); + } + + if (sizeof(supported) > size) { + errno = ERANGE; + return -1; + } + + /* this can't be strcpy() because there are embedded null characters */ + memcpy(list, supported, sizeof(supported)); + return sizeof(supported); +} + + +/* + * Open a print file to be written to by other calls + */ + +static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname) +{ + fstring server, share, user, password; + pstring path; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; + return NULL; + + } + + if (!fname) { + + errno = EINVAL; + return NULL; + + } + + DEBUG(4, ("smbc_open_print_job_ctx(%s)\n", fname)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + /* What if the path is empty, or the file exists? */ + + return context->open(context, fname, O_WRONLY, 666); + +} + +/* + * Routine to print a file on a remote server ... + * + * We open the file, which we assume to be on a remote server, and then + * copy it to a print file on the share specified by printq. + */ + +static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_print, const char *printq) +{ + SMBCFILE *fid1, *fid2; + int bytes, saverr, tot_bytes = 0; + char buf[4096]; + + if (!c_file || !c_file->internal->_initialized || !c_print || + !c_print->internal->_initialized) { + + errno = EINVAL; + return -1; + + } + + if (!fname && !printq) { + + errno = EINVAL; + return -1; + + } + + /* Try to open the file for reading ... */ + + if ((int)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) { + + DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno)); + return -1; /* smbc_open sets errno */ + + } + + /* Now, try to open the printer file for writing */ + + if ((int)(fid2 = c_print->open_print_job(c_print, printq)) < 0) { + + saverr = errno; /* Save errno */ + c_file->close(c_file, fid1); + errno = saverr; + return -1; + + } + + while ((bytes = c_file->read(c_file, fid1, buf, sizeof(buf))) > 0) { + + tot_bytes += bytes; + + if ((c_print->write(c_print, fid2, buf, bytes)) < 0) { + + saverr = errno; + c_file->close(c_file, fid1); + c_print->close(c_print, fid2); + errno = saverr; + + } + + } + + saverr = errno; + + c_file->close(c_file, fid1); /* We have to close these anyway */ + c_print->close(c_print, fid2); + + if (bytes < 0) { + + errno = saverr; + return -1; + + } + + return tot_bytes; + +} + +/* + * Routine to list print jobs on a printer share ... + */ + +static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_list_print_job_fn fn) +{ + SMBCSRV *srv; + fstring server, share, user, password, workgroup; + pstring path; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; + return -1; + + } + + if (!fname) { + + errno = EINVAL; + return -1; + + } + + DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + if (user[0] == (char)0) fstrcpy(user, context->user); + + fstrcpy(workgroup, context->workgroup); + + srv = smbc_server(context, server, share, workgroup, user, password); + + if (!srv) { + + return -1; /* errno set by smbc_server */ + + } + + if (cli_print_queue(&srv->cli, (void (*)(struct print_job_info *))fn) < 0) { + + errno = smbc_errno(context, &srv->cli); + return -1; + + } + + return 0; + +} + +/* + * Delete a print job from a remote printer share + */ + +static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id) +{ + SMBCSRV *srv; + fstring server, share, user, password, workgroup; + pstring path; + int err; + + if (!context || !context->internal || + !context->internal->_initialized) { + + errno = EINVAL; + return -1; + + } + + if (!fname) { + + errno = EINVAL; + return -1; + + } + + DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname)); + + smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/ + + if (user[0] == (char)0) fstrcpy(user, context->user); + + fstrcpy(workgroup, context->workgroup); + + srv = smbc_server(context, server, share, workgroup, user, password); + + if (!srv) { + + return -1; /* errno set by smbc_server */ + + } + + if ((err = cli_printjob_del(&srv->cli, id)) != 0) { + + if (err < 0) + errno = smbc_errno(context, &srv->cli); + else if (err == ERRnosuchprintjob) + errno = EINVAL; + return -1; + + } + + return 0; + +} + +/* + * Get a new empty handle to fill in with your own info + */ +SMBCCTX * smbc_new_context(void) +{ + SMBCCTX * context; + + context = malloc(sizeof(SMBCCTX)); + if (!context) { + errno = ENOMEM; + return NULL; + } + + ZERO_STRUCTP(context); + + context->internal = malloc(sizeof(struct smbc_internal_data)); + if (!context->internal) { + errno = ENOMEM; + return NULL; + } + + ZERO_STRUCTP(context->internal); + + + /* ADD REASONABLE DEFAULTS */ + context->debug = 0; + context->timeout = 20000; /* 20 seconds */ + + context->open = smbc_open_ctx; + context->creat = smbc_creat_ctx; + context->read = smbc_read_ctx; + context->write = smbc_write_ctx; + context->close = smbc_close_ctx; + context->unlink = smbc_unlink_ctx; + context->rename = smbc_rename_ctx; + context->lseek = smbc_lseek_ctx; + context->stat = smbc_stat_ctx; + context->fstat = smbc_fstat_ctx; + context->opendir = smbc_opendir_ctx; + context->closedir = smbc_closedir_ctx; + context->readdir = smbc_readdir_ctx; + context->getdents = smbc_getdents_ctx; + context->mkdir = smbc_mkdir_ctx; + context->rmdir = smbc_rmdir_ctx; + context->telldir = smbc_telldir_ctx; + context->lseekdir = smbc_lseekdir_ctx; + context->fstatdir = smbc_fstatdir_ctx; + context->chmod = smbc_chmod_ctx; + context->utimes = smbc_utimes_ctx; + context->setxattr = smbc_setxattr_ctx; + context->getxattr = smbc_getxattr_ctx; + context->removexattr = smbc_removexattr_ctx; + context->listxattr = smbc_listxattr_ctx; + context->open_print_job = smbc_open_print_job_ctx; + context->print_file = smbc_print_file_ctx; + context->list_print_jobs = smbc_list_print_jobs_ctx; + context->unlink_print_job = smbc_unlink_print_job_ctx; + + context->callbacks.check_server_fn = smbc_check_server; + context->callbacks.remove_unused_server_fn = smbc_remove_unused_server; + + smbc_default_cache_functions(context); + + return context; +} + +/* + * Free a context + * + * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed + * and thus you'll be leaking memory if not handled properly. + * + */ +int smbc_free_context(SMBCCTX * context, int shutdown_ctx) +{ + if (!context) { + errno = EBADF; + return 1; + } + + if (shutdown_ctx) { + SMBCFILE * f; + DEBUG(1,("Performing aggressive shutdown.\n")); + + f = context->internal->_files; + while (f) { + context->close(context, f); + f = f->next; + } + context->internal->_files = NULL; + + /* First try to remove the servers the nice way. */ + if (context->callbacks.purge_cached_fn(context)) { + SMBCSRV * s; + DEBUG(1, ("Could not purge all servers, Nice way shutdown failed.\n")); + s = context->internal->_servers; + while (s) { + cli_shutdown(&s->cli); + context->callbacks.remove_cached_srv_fn(context, s); + SAFE_FREE(s); + s = s->next; + } + context->internal->_servers = NULL; + } + } + else { + /* This is the polite way */ + if (context->callbacks.purge_cached_fn(context)) { + DEBUG(1, ("Could not purge all servers, free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->internal->_servers) { + DEBUG(1, ("Active servers in context, free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->internal->_files) { + DEBUG(1, ("Active files in context, free_context failed.\n")); + errno = EBUSY; + return 1; + } + } + + /* Things we have to clean up */ + SAFE_FREE(context->workgroup); + SAFE_FREE(context->netbios_name); + SAFE_FREE(context->user); + + DEBUG(3, ("Context %p succesfully freed\n", context)); + SAFE_FREE(context->internal); + SAFE_FREE(context); + return 0; +} + + +/* + * Initialise the library etc + * + * We accept a struct containing handle information. + * valid values for info->debug from 0 to 100, + * and insist that info->fn must be non-null. + */ +SMBCCTX * smbc_init_context(SMBCCTX * context) +{ + pstring conf; + int pid; + char *user = NULL, *home = NULL; + + if (!context || !context->internal) { + errno = EBADF; + return NULL; + } + + /* Do not initialise the same client twice */ + if (context->internal->_initialized) { + return 0; + } + + if (!context->callbacks.auth_fn || context->debug < 0 || context->debug > 100) { + + errno = EINVAL; + return NULL; + + } + + if (!smbc_initialized) { + /* Do some library wide intialisations the first time we get called */ + + /* Set this to what the user wants */ + DEBUGLEVEL = context->debug; + + setup_logging( "libsmbclient", True); + + /* Here we would open the smb.conf file if needed ... */ + + home = getenv("HOME"); + + slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home); + + load_interfaces(); /* Load the list of interfaces ... */ + + in_client = True; /* FIXME, make a param */ + + if (!lp_load(conf, True, False, False)) { + + /* + * Well, if that failed, try the dyn_CONFIGFILE + * Which points to the standard locn, and if that + * fails, silently ignore it and use the internal + * defaults ... + */ + + if (!lp_load(dyn_CONFIGFILE, True, False, False)) { + DEBUG(5, ("Could not load either config file: %s or %s\n", + conf, dyn_CONFIGFILE)); + } + } + + reopen_logs(); /* Get logging working ... */ + + /* + * Block SIGPIPE (from lib/util_sock.c: write()) + * It is not needed and should not stop execution + */ + BlockSignals(True, SIGPIPE); + + /* Done with one-time initialisation */ + smbc_initialized = 1; + + } + + if (!context->user) { + /* + * FIXME: Is this the best way to get the user info? + */ + user = getenv("USER"); + /* walk around as "guest" if no username can be found */ + if (!user) context->user = strdup("guest"); + else context->user = strdup(user); + } + + if (!context->netbios_name) { + /* + * We try to get our netbios name from the config. If that fails we fall + * back on constructing our netbios name from our hostname etc + */ + if (global_myname()) { + context->netbios_name = strdup(global_myname()); + } + else { + /* + * Hmmm, I want to get hostname as well, but I am too lazy for the moment + */ + pid = sys_getpid(); + context->netbios_name = malloc(17); + if (!context->netbios_name) { + errno = ENOMEM; + return NULL; + } + slprintf(context->netbios_name, 16, "smbc%s%d", context->user, pid); + } + } + + DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); + + if (!context->workgroup) { + if (lp_workgroup()) { + context->workgroup = strdup(lp_workgroup()); + } + else { + /* TODO: Think about a decent default workgroup */ + context->workgroup = strdup("samba"); + } + } + + DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); + + /* shortest timeout is 1 second */ + if (context->timeout > 0 && context->timeout < 1000) + context->timeout = 1000; + + /* + * FIXME: Should we check the function pointers here? + */ + + context->internal->_initialized = 1; + + return context; } -- cgit From 49da8712d0b9b2298d7681146e83c347001b6c4e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 23 Oct 2003 13:46:32 +0000 Subject: Merge from 3_0: According to Ethereal we have a 32-Bit quantity here. And with SSVAL valgrind reports an unitialized read which is obviously correct. And I hate valgrind errors ;-) Volker (This used to be commit 73fc6da6cf2b52f65c3dbfb7705899e6cbea447a) --- source3/libsmb/clisecdesc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c index 548cd6ec18..2989966f4d 100644 --- a/source3/libsmb/clisecdesc.c +++ b/source3/libsmb/clisecdesc.c @@ -33,7 +33,7 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, SEC_DESC *psd = NULL; SIVAL(param, 0, fnum); - SSVAL(param, 4, 0x7); + SIVAL(param, 4, 0x7); if (!cli_send_nt_trans(cli, NT_TRANSACT_QUERY_SECURITY_DESC, -- cgit From 8e1dfc52b91f38ab53c8f717cb8b952c49a501bb Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 23 Oct 2003 13:47:21 +0000 Subject: Volker's fix for bug #668. Change the \n after the password prompt to go to tty instead of stdout. (This used to be commit fb503bb418fcbee20d2218650904b26b512106ed) --- source3/lib/getsmbpass.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/lib/getsmbpass.c b/source3/lib/getsmbpass.c index 27cd5e6dfa..df5e0359aa 100644 --- a/source3/lib/getsmbpass.c +++ b/source3/lib/getsmbpass.c @@ -158,14 +158,15 @@ char *getsmbpass(const char *prompt) tcsetattr (fileno (in), TCSANOW, &t); } + fprintf(out, "\n"); + fflush(out); + if (in != stdin) /* We opened the terminal; now close it. */ fclose(in); /* Catch problematic signals */ CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - printf("\n"); - if (gotintr) { printf("Interupted by signal.\n"); fflush(stdout); -- cgit From 2a09fe6cb4e31e46dd92052bbc134629b4ae8fda Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 23 Oct 2003 14:33:21 +0000 Subject: Fix bug 451. Stop net -P from prompting for machine account password. Based on work by Ken Cross (kcross@nssolutions.com). (This used to be commit 32aa749bf1328e43af629ade30b3fdc11dd5e3ec) --- source3/utils/net.c | 4 ++-- source3/utils/net.h | 1 + source3/utils/net_ads.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/utils/net.c b/source3/utils/net.c index 38c144caa8..75fa607cae 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -72,7 +72,7 @@ const char *opt_container = "cn=Users"; int opt_flags = -1; int opt_timeout = 0; const char *opt_target_workgroup = NULL; -static int opt_machine_pass = 0; +int opt_machine_pass = 0; BOOL opt_have_ip = False; struct in_addr opt_dest_ip; @@ -130,7 +130,7 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip, { NTSTATUS nt_status; - if (!opt_password) { + if (!opt_password && !opt_machine_pass) { char *pass = getpass("Password:"); if (pass) { opt_password = strdup(pass); diff --git a/source3/utils/net.h b/source3/utils/net.h index f83d0169bf..78c0aad86a 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -48,6 +48,7 @@ extern const char *opt_workgroup; extern int opt_long_list_entries; extern int opt_reboot; extern int opt_force; +extern int opt_machine_pass; extern int opt_timeout; extern const char *opt_host; extern const char *opt_user_name; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 3b955742d8..cad93608dc 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -145,7 +145,7 @@ static ADS_STRUCT *ads_startup(void) } retry: - if (!opt_password && need_password) { + if (!opt_password && need_password && !opt_machine_pass) { char *prompt; asprintf(&prompt,"%s password: ", opt_user_name); opt_password = getpass(prompt); -- cgit From a36be30e082d0208ca8b6215928069e9f3d4f7b0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 23 Oct 2003 16:51:08 +0000 Subject: Merge from 3_0: After a phonecall with jra finally commit this. This changes our behaviour when the setresuid call is available. We now not only change the effective uid but also the real uid when becoming unprivileged. This is mainly for improved AFS compatibility, as AFS selects the token to send to the server based on the real uid of the process. I tested this with a W2k server with two non-root 'runas' sessions. They come in via a single smbd as two different users using two session setups. Samba on Linux can still switch between the two uids, proved by two different files created via those sessions. Volker (This used to be commit 8a75e2dfb6ee9099e7f9a970c522e71ab144d919) --- source3/lib/afs.c | 10 +++------- source3/lib/util_sec.c | 7 ++----- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'source3') diff --git a/source3/lib/afs.c b/source3/lib/afs.c index 882442a79f..fc78950f39 100644 --- a/source3/lib/afs.c +++ b/source3/lib/afs.c @@ -185,13 +185,9 @@ BOOL afs_login(connection_struct *conn) strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; - /* As long as we still only use the effective UID we need to set the - * token for it here as well. This involves patching AFS in two - * places. Once we start using the real uid where we have the - * setresuid function, we can use getuid() here which would be more - * correct. */ - - ct.ViceId = geteuid(); + /* This assumes that we have setresuid and set the real uid as well as + the effective uid in set_effective_uid(). */ + ct.ViceId = getuid(); DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); /* Alice's network layer address. At least Openafs-1.2.10 diff --git a/source3/lib/util_sec.c b/source3/lib/util_sec.c index 1980b8bfb7..7c2576ed91 100644 --- a/source3/lib/util_sec.c +++ b/source3/lib/util_sec.c @@ -183,11 +183,8 @@ void gain_root_group_privilege(void) void set_effective_uid(uid_t uid) { #if USE_SETRESUID - /* On Systems which have this function, would it not be more - * appropriate to also set the real uid by doing - * setresuid(uid,uid,-1)? This would make patching AFS - * unnecessary. See comment in lib/afs.c. */ - setresuid(-1,uid,-1); + /* Set the effective as well as the real uid. */ + setresuid(uid,uid,-1); #endif #if USE_SETREUID -- cgit From 7967eeb659574932cdaa770941afbcfd2e991a3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Oct 2003 01:19:23 +0000 Subject: Andrew Bartlett patch to cope with Exchange 5.5 cleartext pop password auth. Jeremy. (This used to be commit 2d09d8c9d973f5f414d31f749db12328ff315de7) --- source3/auth/auth_sam.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3') diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index ce97bd7df2..2a00b6fb80 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -172,6 +172,22 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, pdb_get_username(sampass))); /* No return, we want to check the LM hash below in this case */ auth_flags &= (~(AUTH_FLAG_NTLMv2_RESP | AUTH_FLAG_NTLM_RESP)); + } else { + /* Check for cleartext netlogon. Used by Exchange 5.5. */ + unsigned char zeros[8]; + + memset(zeros,'\0',sizeof(zeros)); + if (auth_context->challenge.length == sizeof(zeros) && + (memcmp(auth_context->challenge.data, zeros, auth_context->challenge.length) == 0 ) && + user_info->nt_resp.length) { + if ((nt_pw = pdb_get_nt_passwd(sampass)) != NULL) { + unsigned char pwhash[16]; + mdfour(pwhash, user_info->nt_resp.data, user_info->nt_resp.length); + if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { + return NT_STATUS_OK; + } + } + } } if (auth_flags & AUTH_FLAG_NTLMv2_RESP) { -- cgit From 261c0028dcc3d15f82ed7f5db6cb89fc77083418 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 24 Oct 2003 05:47:39 +0000 Subject: Check for va_copy before you check for __va_copy, since va_copy is the actual standard, and __va_copy was the proposed standard. (This used to be commit 4ab7947e601e61cacd7ff541ee881850d9808387) --- source3/configure.in | 18 ++++++++++++++---- source3/lib/snprintf.c | 4 ++++ 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index 01c71b3149..bbf26c916d 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1391,12 +1391,22 @@ if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) fi -AC_CACHE_CHECK([for __va_copy],samba_cv_HAVE_VA_COPY,[ +AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[ AC_TRY_LINK([#include -va_list ap1,ap2;], [__va_copy(ap1,ap2);], -samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)]) +va_list ap1,ap2;], [va_copy(ap1,ap2);], +samba_cv_HAVE_VA_COPY=yes, +samba_cv_HAVE_VA_COPY=no)]) if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then - AC_DEFINE(HAVE_VA_COPY,1,[Whether __va_copy() is available]) + AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) +else + AC_CACHE_CHECK([for __va_copy],samba_cv_HAVE___VA_COPY,[ + AC_TRY_LINK([#include + va_list ap1,ap2;], [__va_copy(ap1,ap2);], + samba_cv_HAVE___VA_COPY=yes, + samba_cv_HAVE___VA_COPY=no)]) + if test x"$samba_cv_HAVE___VA_COPY" = x"yes"; then + AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available]) + fi fi AC_CACHE_CHECK([for C99 vsnprintf],samba_cv_HAVE_C99_VSNPRINTF,[ diff --git a/source3/lib/snprintf.c b/source3/lib/snprintf.c index a2f9f592db..5b0cfa1ab3 100644 --- a/source3/lib/snprintf.c +++ b/source3/lib/snprintf.c @@ -147,10 +147,14 @@ #ifndef VA_COPY #ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#else +#ifdef HAVE___VA_COPY #define VA_COPY(dest, src) __va_copy(dest, src) #else #define VA_COPY(dest, src) (dest) = (src) #endif +#endif /* * dopr(): poor man's version of doprintf -- cgit From 6258550534050e59a80ae8e39d9fb308b2e648fb Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 24 Oct 2003 13:38:13 +0000 Subject: New files for support of initshutdown pipe. Win2k doesn't respond properly to all requests on the winreg pipe, so we need to handle this new pipe. First part of fix for bug #534 (This used to be commit 532fab74c12d8c55872c2bad2abead2647f919d7) --- source3/include/rpc_shutdown.h | 70 ++++++++++++++++ source3/rpc_client/cli_shutdown.c | 104 +++++++++++++++++++++++ source3/rpc_parse/parse_shutdown.c | 163 +++++++++++++++++++++++++++++++++++++ source3/rpcclient/cmd_shutdown.c | 112 +++++++++++++++++++++++++ 4 files changed, 449 insertions(+) create mode 100644 source3/include/rpc_shutdown.h create mode 100644 source3/rpc_client/cli_shutdown.c create mode 100644 source3/rpc_parse/parse_shutdown.c create mode 100644 source3/rpcclient/cmd_shutdown.c (limited to 'source3') diff --git a/source3/include/rpc_shutdown.h b/source3/include/rpc_shutdown.h new file mode 100644 index 0000000000..b8e50b835f --- /dev/null +++ b/source3/include/rpc_shutdown.h @@ -0,0 +1,70 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_SHUTDOWN_H /* _RPC_SHUTDOWN_H */ +#define _RPC_SHUTDOWN_H + + +/* Implemented */ +#define SHUTDOWN_INIT 0x00 +#define SHUTDOWN_ABORT 0x01 +/* NOT IMPLEMENTED +#define SHUTDOWN_INIT_EX 0x02 +*/ + +/* SHUTDOWN_Q_INIT */ +typedef struct q_shutodwn_init_info +{ + uint32 ptr_server; + uint16 server; + uint32 ptr_msg; + UNIHDR hdr_msg; /* shutdown message */ + UNISTR2 uni_msg; /* seconds */ + uint32 timeout; /* seconds */ + uint8 force; /* boolean: force shutdown */ + uint8 reboot; /* boolean: reboot on shutdown */ + +} SHUTDOWN_Q_INIT; + +/* SHUTDOWN_R_INIT */ +typedef struct r_shutdown_init_info +{ + NTSTATUS status; /* return status */ + +} SHUTDOWN_R_INIT; + +/* SHUTDOWN_Q_ABORT */ +typedef struct q_shutdown_abort_info +{ + uint32 ptr_server; + uint16 server; + +} SHUTDOWN_Q_ABORT; + +/* SHUTDOWN_R_ABORT */ +typedef struct r_shutdown_abort_info +{ + NTSTATUS status; /* return status */ + +} SHUTDOWN_R_ABORT; + + +#endif /* _RPC_SHUTDOWN_H */ + diff --git a/source3/rpc_client/cli_shutdown.c b/source3/rpc_client/cli_shutdown.c new file mode 100644 index 0000000000..0bf6e90ad2 --- /dev/null +++ b/source3/rpc_client/cli_shutdown.c @@ -0,0 +1,104 @@ +/* + Unix SMB/CIFS implementation. + RPC Pipe client + + Copyright (C) Andrew Tridgell 1992-1998, + Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + Copyright (C) Paul Ashton 1997-1998. + Copyright (C) Jeremy Allison 1999, + Copyright (C) Simo Sorce 2001, + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* Shutdown a server */ + +NTSTATUS cli_shutdown_init(struct cli_state * cli, TALLOC_CTX *mem_ctx, + const char *msg, uint32 timeout, BOOL do_reboot, + BOOL force) +{ + prs_struct qbuf; + prs_struct rbuf; + SHUTDOWN_Q_INIT q_s; + SHUTDOWN_R_INIT r_s; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + if (msg == NULL) return NT_STATUS_INVALID_PARAMETER; + + ZERO_STRUCT (q_s); + ZERO_STRUCT (r_s); + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_shutdown_q_init(&q_s, msg, timeout, do_reboot, force); + + if (!shutdown_io_q_init("", &q_s, &qbuf, 0) || + !rpc_api_pipe_req(cli, SHUTDOWN_INIT, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if(shutdown_io_r_init("", &r_s, &rbuf, 0)) + result = r_s.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + + +/* Abort a server shutdown */ + +NTSTATUS cli_shutdown_abort(struct cli_state * cli, TALLOC_CTX *mem_ctx) +{ + prs_struct rbuf; + prs_struct qbuf; + SHUTDOWN_Q_ABORT q_s; + SHUTDOWN_R_ABORT r_s; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT (q_s); + ZERO_STRUCT (r_s); + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_shutdown_q_abort(&q_s); + + if (!shutdown_io_q_abort("", &q_s, &qbuf, 0) || + !rpc_api_pipe_req(cli, SHUTDOWN_ABORT, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (shutdown_io_r_abort("", &r_s, &rbuf, 0)) + result = r_s.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf ); + + return result; +} diff --git a/source3/rpc_parse/parse_shutdown.c b/source3/rpc_parse/parse_shutdown.c new file mode 100644 index 0000000000..ad2d6e1a02 --- /dev/null +++ b/source3/rpc_parse/parse_shutdown.c @@ -0,0 +1,163 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* +Inits a structure. +********************************************************************/ + +void init_shutdown_q_init(SHUTDOWN_Q_INIT *q_s, const char *msg, + uint32 timeout, BOOL do_reboot, BOOL force) +{ + q_s->ptr_server = 1; + q_s->server = 1; + q_s->ptr_msg = 1; + + init_unistr2(&q_s->uni_msg, msg, UNI_FLAGS_NONE); + init_uni_hdr(&q_s->hdr_msg, &q_s->uni_msg); + + q_s->timeout = timeout; + + q_s->reboot = do_reboot ? 1 : 0; + q_s->force = force ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL shutdown_io_q_init(const char *desc, SHUTDOWN_Q_INIT *q_s, prs_struct *ps, + int depth) +{ + if (q_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_q_init"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("ptr_server", ps, depth, &(q_s->ptr_server))) + return False; + if (!prs_uint16("server", ps, depth, &(q_s->server))) + return False; + + if (!prs_align(ps)) + return False; + if (!prs_uint32("ptr_msg", ps, depth, &(q_s->ptr_msg))) + return False; + + if (!smb_io_unihdr("hdr_msg", &(q_s->hdr_msg), ps, depth)) + return False; + if (!smb_io_unistr2("uni_msg", &(q_s->uni_msg), q_s->hdr_msg.buffer, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + + if (!prs_uint32("timeout", ps, depth, &(q_s->timeout))) + return False; + if (!prs_uint8("force ", ps, depth, &(q_s->force))) + return False; + if (!prs_uint8("reboot ", ps, depth, &(q_s->reboot))) + return False; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL shutdown_io_r_init(const char *desc, SHUTDOWN_R_INIT* r_s, prs_struct *ps, + int depth) +{ + if (r_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_r_init"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_s->status)) + return False; + + return True; +} + +/******************************************************************* +Inits a structure. +********************************************************************/ +void init_shutdown_q_abort(SHUTDOWN_Q_ABORT *q_s) +{ + + q_s->ptr_server = 0; + +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL shutdown_io_q_abort(const char *desc, SHUTDOWN_Q_ABORT *q_s, + prs_struct *ps, int depth) +{ + if (q_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_q_abort"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("ptr_server", ps, depth, &(q_s->ptr_server))) + return False; + if (q_s->ptr_server != 0) + if (!prs_uint16("server", ps, depth, &(q_s->server))) + return False; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL shutdown_io_r_abort(const char *desc, SHUTDOWN_R_ABORT *r_s, + prs_struct *ps, int depth) +{ + if (r_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_r_abort"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_ntstatus("status", ps, depth, &r_s->status)) + return False; + + return True; +} diff --git a/source3/rpcclient/cmd_shutdown.c b/source3/rpcclient/cmd_shutdown.c new file mode 100644 index 0000000000..e42ec30ac1 --- /dev/null +++ b/source3/rpcclient/cmd_shutdown.c @@ -0,0 +1,112 @@ +/* + Unix SMB/CIFS implementation. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-1997, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + Copyright (C) Simo Sorce 2001, + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "rpcclient.h" + +/**************************************************************************** +nt shutdown init +****************************************************************************/ +static NTSTATUS cmd_shutdown_init(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring msg; + uint32 timeout = 20; + BOOL force = False; + BOOL reboot = False; + int opt; + + *msg = 0; + optind = 0; /* TODO: test if this hack works on other systems too --simo */ + + while ((opt = getopt(argc, argv, "m:t:rf")) != EOF) + { + /*fprintf (stderr, "[%s]\n", argv[argc-1]);*/ + + switch (opt) + { + case 'm': + fstrcpy(msg, optarg); + /*fprintf (stderr, "[%s|%s]\n", optarg, msg);*/ + break; + + case 't': + timeout = atoi(optarg); + /*fprintf (stderr, "[%s|%d]\n", optarg, timeout);*/ + break; + + case 'r': + reboot = True; + break; + + case 'f': + force = True; + break; + + } + } + + /* create an entry */ + result = cli_shutdown_init(cli, mem_ctx, msg, timeout, reboot, force); + + if (NT_STATUS_IS_OK(result)) + DEBUG(5,("cmd_shutdown_init: query succeeded\n")); + else + DEBUG(5,("cmd_shutdown_init: query failed\n")); + + return result; +} + +/**************************************************************************** +abort a shutdown +****************************************************************************/ +static NTSTATUS cmd_shutdown_abort(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + result = cli_shutdown_abort(cli, mem_ctx); + + if (NT_STATUS_IS_OK(result)) + DEBUG(5,("cmd_shutdown_abort: query succeeded\n")); + else + DEBUG(5,("cmd_shutdown_abort: query failed\n")); + + return result; +} + + +/* List of commands exported by this module */ +struct cmd_set shutdown_commands[] = { + + { "SHUTDOWN" }, + + { "shutdowninit", RPC_RTYPE_NTSTATUS, cmd_shutdown_init, NULL, PI_SHUTDOWN, "Remote Shutdown (over shutdown pipe)", + "syntax: shutdown [-m message] [-t timeout] [-r] [-h] [-f] (-r == reboot, -h == halt, -f == force)" }, + + { "shutdownabort", RPC_RTYPE_NTSTATUS, cmd_shutdown_abort, NULL, PI_SHUTDOWN, "Abort Shutdown (over shutdown pipe)", + "syntax: shutdownabort" }, + { NULL } +}; -- cgit