From 177db0a8802842a0eb9801622bee9f4c1592ef88 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 19 Aug 2011 17:28:37 +0200 Subject: [PATCH] s3-id_cache: Move id caches mgmt out of smbd We must leave the MSG_IDMAP_KILL operation in SMBD as it uses smbd specific internal globals and makes sense only in the context of a smbd daemon. The rest is moved under lib/ as we need to deal with id cache cleanups in other daemons too (like lsasd). Signed-off-by: Simo Sorce --- source3/Makefile.in | 1 + source3/lib/id_cache.c | 190 ++++++++++++++++++++++++++++++++++++ source3/lib/id_cache.h | 32 ++++++ source3/passdb/lookup_sid.c | 65 ------------ source3/passdb/lookup_sid.h | 5 - source3/smbd/msg_idmap.c | 110 ++------------------- source3/smbd/proto.h | 2 +- source3/smbd/server.c | 2 + source3/wscript_build | 1 + 9 files changed, 237 insertions(+), 171 deletions(-) create mode 100644 source3/lib/id_cache.c create mode 100644 source3/lib/id_cache.h diff --git a/source3/Makefile.in b/source3/Makefile.in index 4937f3003e..39e62cce39 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -431,6 +431,7 @@ CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) $(LIBTSOCKET_OBJ) \ lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o \ lib/messages_ctdbd.o lib/ctdb_packet.o lib/ctdbd_conn.o \ + lib/id_cache.o \ ../lib/socket/interfaces.o lib/memcache.o \ lib/talloc_dict.o \ lib/serverid.o \ diff --git a/source3/lib/id_cache.c b/source3/lib/id_cache.c new file mode 100644 index 0000000000..50649dd409 --- /dev/null +++ b/source3/lib/id_cache.c @@ -0,0 +1,190 @@ +/* + * Samba Unix/Linux SMB client library + * + * Copyright (C) Gregor Beck 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @brief Notify smbd about idmap changes + * @file msg_idmap.c + * @author Gregor Beck + * @date Feb 2011 + * + */ + +#include "includes.h" +#include "messages.h" +#include "lib/id_cache.h" +#include "include/memcache.h" +#include "idmap_cache.h" +#include "../librpc/gen_ndr/ndr_security.h" +#include "../libcli/security/dom_sid.h" + +bool id_cache_ref_parse(const char* str, struct id_cache_ref* id) +{ + struct dom_sid sid; + unsigned long ul; + char c, trash; + + if (sscanf(str, "%cID %lu%c", &c, &ul, &trash) == 2) { + switch(c) { + case 'G': + id->id.gid = ul; + id->type = GID; + return true; + case 'U': + id->id.uid = ul; + id->type = UID; + return true; + default: + break; + } + } else if (string_to_sid(&sid, str)) { + id->id.sid = sid; + id->type = SID; + return true; + } + return false; +} + +static bool delete_uid_cache(uid_t puid) +{ + DATA_BLOB uid = data_blob_const(&puid, sizeof(puid)); + DATA_BLOB sid; + + if (!memcache_lookup(NULL, UID_SID_CACHE, uid, &sid)) { + DEBUG(3, ("UID %d is not memcached!\n", (int)puid)); + return false; + } + DEBUG(3, ("Delete mapping UID %d <-> %s from memcache\n", (int)puid, + sid_string_dbg((struct dom_sid*)sid.data))); + memcache_delete(NULL, SID_UID_CACHE, sid); + memcache_delete(NULL, UID_SID_CACHE, uid); + return true; +} + +static bool delete_gid_cache(gid_t pgid) +{ + DATA_BLOB gid = data_blob_const(&pgid, sizeof(pgid)); + DATA_BLOB sid; + if (!memcache_lookup(NULL, GID_SID_CACHE, gid, &sid)) { + DEBUG(3, ("GID %d is not memcached!\n", (int)pgid)); + return false; + } + DEBUG(3, ("Delete mapping GID %d <-> %s from memcache\n", (int)pgid, + sid_string_dbg((struct dom_sid*)sid.data))); + memcache_delete(NULL, SID_GID_CACHE, sid); + memcache_delete(NULL, GID_SID_CACHE, gid); + return true; +} + +static bool delete_sid_cache(const struct dom_sid* psid) +{ + DATA_BLOB sid = data_blob_const(psid, ndr_size_dom_sid(psid, 0)); + DATA_BLOB id; + if (memcache_lookup(NULL, SID_GID_CACHE, sid, &id)) { + DEBUG(3, ("Delete mapping %s <-> GID %d from memcache\n", + sid_string_dbg(psid), *(int*)id.data)); + memcache_delete(NULL, SID_GID_CACHE, sid); + memcache_delete(NULL, GID_SID_CACHE, id); + } else if (memcache_lookup(NULL, SID_UID_CACHE, sid, &id)) { + DEBUG(3, ("Delete mapping %s <-> UID %d from memcache\n", + sid_string_dbg(psid), *(int*)id.data)); + memcache_delete(NULL, SID_UID_CACHE, sid); + memcache_delete(NULL, UID_SID_CACHE, id); + } else { + DEBUG(3, ("SID %s is not memcached!\n", sid_string_dbg(psid))); + return false; + } + return true; +} + +static void flush_gid_cache(void) +{ + DEBUG(3, ("Flush GID <-> SID memcache\n")); + memcache_flush(NULL, SID_GID_CACHE); + memcache_flush(NULL, GID_SID_CACHE); +} + +static void flush_uid_cache(void) +{ + DEBUG(3, ("Flush UID <-> SID memcache\n")); + memcache_flush(NULL, SID_UID_CACHE); + memcache_flush(NULL, UID_SID_CACHE); +} +static void delete_from_cache(const struct id_cache_ref* id) +{ + switch(id->type) { + case UID: + delete_uid_cache(id->id.uid); + idmap_cache_del_uid(id->id.uid); + break; + case GID: + delete_gid_cache(id->id.gid); + idmap_cache_del_gid(id->id.gid); + break; + case SID: + delete_sid_cache(&id->id.sid); + idmap_cache_del_sid(&id->id.sid); + break; + default: + break; + } +} + + +static void message_idmap_flush(struct messaging_context *msg_ctx, + void* private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB* data) +{ + const char *msg = data ? (const char *)data->data : NULL; + + if ((msg == NULL) || (msg[0] == '\0')) { + flush_gid_cache(); + flush_uid_cache(); + } else if (strncmp(msg, "GID", 3)) { + flush_gid_cache(); + } else if (strncmp(msg, "UID", 3)) { + flush_uid_cache(); + } else { + DEBUG(0, ("Invalid argument: %s\n", msg)); + } +} + +static void message_idmap_delete(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB* data) +{ + const char *msg = (data && data->data) ? (const char *)data->data : ""; + struct id_cache_ref id; + + if (!id_cache_ref_parse(msg, &id)) { + DEBUG(0, ("Invalid ?ID: %s\n", msg)); + return; + } + + delete_from_cache(&id); +} + +void msg_idmap_register_msgs(struct messaging_context *ctx) +{ + messaging_register(ctx, NULL, MSG_IDMAP_FLUSH, message_idmap_flush); + messaging_register(ctx, NULL, MSG_IDMAP_DELETE, message_idmap_delete); +} diff --git a/source3/lib/id_cache.h b/source3/lib/id_cache.h new file mode 100644 index 0000000000..fc78f75192 --- /dev/null +++ b/source3/lib/id_cache.h @@ -0,0 +1,32 @@ +/* + * Samba Unix/Linux SMB client library + * + * Copyright (C) Gregor Beck 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct id_cache_ref { + union { + uid_t uid; + gid_t gid; + struct dom_sid sid; + const char *name; + } id; + enum {UID, GID, SID, NAME} type; +}; + +bool id_cache_ref_parse(const char* str, struct id_cache_ref* id); + +void msg_idmap_register_msgs(struct messaging_context *ctx); diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 8b5330c097..4c2e73befd 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1745,68 +1745,3 @@ done: return NT_STATUS_OK; } -bool delete_uid_cache(uid_t puid) -{ - DATA_BLOB uid = data_blob_const(&puid, sizeof(puid)); - DATA_BLOB sid; - - if (!memcache_lookup(NULL, UID_SID_CACHE, uid, &sid)) { - DEBUG(3, ("UID %d is not memcached!\n", (int)puid)); - return false; - } - DEBUG(3, ("Delete mapping UID %d <-> %s from memcache\n", (int)puid, - sid_string_dbg((struct dom_sid*)sid.data))); - memcache_delete(NULL, SID_UID_CACHE, sid); - memcache_delete(NULL, UID_SID_CACHE, uid); - return true; -} - -bool delete_gid_cache(gid_t pgid) -{ - DATA_BLOB gid = data_blob_const(&pgid, sizeof(pgid)); - DATA_BLOB sid; - if (!memcache_lookup(NULL, GID_SID_CACHE, gid, &sid)) { - DEBUG(3, ("GID %d is not memcached!\n", (int)pgid)); - return false; - } - DEBUG(3, ("Delete mapping GID %d <-> %s from memcache\n", (int)pgid, - sid_string_dbg((struct dom_sid*)sid.data))); - memcache_delete(NULL, SID_GID_CACHE, sid); - memcache_delete(NULL, GID_SID_CACHE, gid); - return true; -} - -bool delete_sid_cache(const struct dom_sid* psid) -{ - DATA_BLOB sid = data_blob_const(psid, ndr_size_dom_sid(psid, 0)); - DATA_BLOB id; - if (memcache_lookup(NULL, SID_GID_CACHE, sid, &id)) { - DEBUG(3, ("Delete mapping %s <-> GID %d from memcache\n", - sid_string_dbg(psid), *(int*)id.data)); - memcache_delete(NULL, SID_GID_CACHE, sid); - memcache_delete(NULL, GID_SID_CACHE, id); - } else if (memcache_lookup(NULL, SID_UID_CACHE, sid, &id)) { - DEBUG(3, ("Delete mapping %s <-> UID %d from memcache\n", - sid_string_dbg(psid), *(int*)id.data)); - memcache_delete(NULL, SID_UID_CACHE, sid); - memcache_delete(NULL, UID_SID_CACHE, id); - } else { - DEBUG(3, ("SID %s is not memcached!\n", sid_string_dbg(psid))); - return false; - } - return true; -} - -void flush_gid_cache(void) -{ - DEBUG(3, ("Flush GID <-> SID memcache\n")); - memcache_flush(NULL, SID_GID_CACHE); - memcache_flush(NULL, GID_SID_CACHE); -} - -void flush_uid_cache(void) -{ - DEBUG(3, ("Flush UID <-> SID memcache\n")); - memcache_flush(NULL, SID_UID_CACHE); - memcache_flush(NULL, UID_SID_CACHE); -} diff --git a/source3/passdb/lookup_sid.h b/source3/passdb/lookup_sid.h index b56aaba039..5ce455d08b 100644 --- a/source3/passdb/lookup_sid.h +++ b/source3/passdb/lookup_sid.h @@ -91,10 +91,5 @@ NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx, const char *username, struct passwd **_pwd, struct dom_sid **_group_sid); -bool delete_uid_cache(uid_t uid); -bool delete_gid_cache(gid_t gid); -bool delete_sid_cache(const struct dom_sid* psid); -void flush_uid_cache(void); -void flush_gid_cache(void); #endif /* _PASSDB_LOOKUP_SID_H_ */ diff --git a/source3/smbd/msg_idmap.c b/source3/smbd/msg_idmap.c index e87b313493..0a24bb1626 100644 --- a/source3/smbd/msg_idmap.c +++ b/source3/smbd/msg_idmap.c @@ -17,58 +17,15 @@ * along with this program. If not, see . */ -/** - * @brief Notify smbd about idmap changes - * @file msg_idmap.c - * @author Gregor Beck - * @date Feb 2011 - * - */ - #include "includes.h" +#include "smbd/globals.h" #include "smbd/smbd.h" -#include "globals.h" #include "../libcli/security/dom_sid.h" #include "idmap_cache.h" #include "passdb/lookup_sid.h" #include "auth.h" #include "messages.h" - -struct id { - union { - uid_t uid; - gid_t gid; - struct dom_sid sid; - } id; - enum {UID, GID, SID} type; -}; - -static bool parse_id(const char* str, struct id* id) -{ - struct dom_sid sid; - unsigned long ul; - char c, trash; - - if (sscanf(str, "%cID %lu%c", &c, &ul, &trash) == 2) { - switch(c) { - case 'G': - id->id.gid = ul; - id->type = GID; - return true; - case 'U': - id->id.uid = ul; - id->type = UID; - return true; - default: - break; - } - } else if (string_to_sid(&sid, str)) { - id->id.sid = sid; - id->type = SID; - return true; - } - return false; -} +#include "lib/id_cache.h" static bool uid_in_use(const struct user_struct* user, uid_t uid) { @@ -113,8 +70,8 @@ static bool sid_in_use(const struct user_struct* user, const struct dom_sid* psi return false; } - -static bool id_in_use(const struct user_struct* user, const struct id* id) +static bool id_in_use(const struct user_struct* user, + const struct id_cache_ref* id) { switch(id->type) { case UID: @@ -129,74 +86,27 @@ static bool id_in_use(const struct user_struct* user, const struct id* id) return false; } -static void delete_from_cache(const struct id* id) -{ - switch(id->type) { - case UID: - delete_uid_cache(id->id.uid); - idmap_cache_del_uid(id->id.uid); - break; - case GID: - delete_gid_cache(id->id.gid); - idmap_cache_del_gid(id->id.gid); - break; - case SID: - delete_sid_cache(&id->id.sid); - idmap_cache_del_sid(&id->id.sid); - break; - default: - break; - } -} - - -static void message_idmap_flush(struct messaging_context *msg_ctx, - void* private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB* data) -{ - const char *msg = data ? (const char *)data->data : NULL; - - if ((msg == NULL) || (msg[0] == '\0')) { - flush_gid_cache(); - flush_uid_cache(); - } else if (strncmp(msg, "GID", 3)) { - flush_gid_cache(); - } else if (strncmp(msg, "UID", 3)) { - flush_uid_cache(); - } else { - DEBUG(0, ("Invalid argument: %s\n", msg)); - } -} - - -static void message_idmap_delete(struct messaging_context *msg_ctx, +static void message_idmap_kill(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB* data) { const char *msg = (data && data->data) ? (const char *)data->data : ""; - bool do_kill = (msg_type == MSG_IDMAP_KILL); struct user_struct *validated_users = smbd_server_conn->smb1.sessions.validated_users; - struct id id; + struct id_cache_ref id; - if (!parse_id(msg, &id)) { + if (!id_cache_ref_parse(msg, &id)) { DEBUG(0, ("Invalid ?ID: %s\n", msg)); return; } - if (do_kill && id_in_use(validated_users, &id)) { + if (id_in_use(validated_users, &id)) { exit_server_cleanly(msg); - } else { - delete_from_cache(&id); } } -void msg_idmap_register_msgs(struct messaging_context *ctx) +void msg_idmap_register_kill_msg(struct messaging_context *ctx) { - messaging_register(ctx, NULL, MSG_IDMAP_FLUSH, message_idmap_flush); - messaging_register(ctx, NULL, MSG_IDMAP_DELETE, message_idmap_delete); - messaging_register(ctx, NULL, MSG_IDMAP_KILL, message_idmap_delete); + messaging_register(ctx, NULL, MSG_IDMAP_KILL, message_idmap_kill); } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index d140813438..554d907d89 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1182,6 +1182,6 @@ void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev, /* The following definitions come from smbd/msg_idmap.c */ -void msg_idmap_register_msgs(struct messaging_context *ctx); +void msg_idmap_register_kill_msg(struct messaging_context *ctx); #endif /* _SMBD_PROTO_H_ */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index cc53f69626..e547d38581 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -39,6 +39,7 @@ #include "auth.h" #include "messages.h" #include "smbprofile.h" +#include "lib/id_cache.h" extern void start_epmd(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx); @@ -749,6 +750,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, brl_register_msgs(msg_ctx); msg_idmap_register_msgs(msg_ctx); + msg_idmap_register_kill_msg(msg_ctx); #ifdef CLUSTER_SUPPORT if (lp_clustering()) { diff --git a/source3/wscript_build b/source3/wscript_build index 3d4e3b43cc..46e9a85387 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -55,6 +55,7 @@ REG_PARSE_PRS_SRC = '''registry/reg_parse_prs.c''' LIB_SRC = ''' lib/messages.c lib/messages_local.c lib/messages_ctdbd.c lib/ctdb_packet.c lib/ctdbd_conn.c + lib/id_cache.c lib/talloc_dict.c lib/util_sconn.c lib/serverid.c -- 2.34.1