# HG changeset patch # User Gordon Ross # Date 1531242319 14400 # Node ID 60e796757b5345226375b37b818390c164a6ff71 # Parent ebeeffcb370f9bab89ced22f6979a88d309a76ef 10992 SMB logon should tolerate idmap problems Reviewed by: Matt Barden Reviewed by: Joyce McIntosh Reviewed by: Yuri Pankov Approved by: Richard Lowe diff -r ebeeffcb370f -r 60e796757b53 usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c --- a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c Wed May 29 17:34:03 2019 +0000 +++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c Tue Jul 10 13:05:19 2018 -0400 @@ -20,17 +20,17 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * SMB server interface to idmap * (smb_idmap_get..., smb_idmap_batch_...) * - * There are three implementations of this interface: - * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod) - * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv) - * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb) + * There are three implementations of this interface. + * This is the "fake kernel" version of these routines. See also: + * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c + * $SRC/uts/common/fs/smbsrv/smb_idmap.c * * There are enough differences (relative to the code size) * that it's more trouble than it's worth to merge them. @@ -39,6 +39,7 @@ * calls idmap interfaces (libidmap) * uses kmem_... interfaces (libfakekernel) * uses cmn_err instead of syslog, etc. + * The code in this variant looks a lot like the one in libsmb. */ #include @@ -148,8 +149,7 @@ { idmap_stat stat; - if (!sib) - return (IDMAP_ERR_ARG); + ASSERT(sib != NULL); bzero(sib, sizeof (smb_idmap_batch_t)); stat = idmap_get_create(&sib->sib_idmaph); @@ -175,19 +175,17 @@ void smb_idmap_batch_destroy(smb_idmap_batch_t *sib) { + char *domsid; int i; - if (sib == NULL) - return; + ASSERT(sib != NULL); + ASSERT(sib->sib_maps != NULL); if (sib->sib_idmaph) { idmap_get_destroy(sib->sib_idmaph); sib->sib_idmaph = NULL; } - if (sib->sib_maps == NULL) - return; - if (sib->sib_flags & SMB_IDMAP_ID2SID) { /* * SIDs are allocated only when mapping @@ -198,6 +196,16 @@ /* from strdup() in libidmap */ free(sib->sib_maps[i].sim_domsid); } + } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { + /* + * SID prefixes are allocated only when mapping + * SIDs to UID/GID + */ + for (i = 0; i < sib->sib_nmap; i++) { + domsid = sib->sib_maps[i].sim_domsid; + if (domsid) + smb_mem_free(domsid); + } } if (sib->sib_size && sib->sib_maps) { @@ -225,13 +233,15 @@ idmap_stat stat; int flag = 0; - if (idmaph == NULL || sim == NULL || sid == NULL) - return (IDMAP_ERR_ARG); + ASSERT(idmaph != NULL); + ASSERT(sim != NULL); + ASSERT(sid != NULL); smb_sid_tostr(sid, sidstr); if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0) return (IDMAP_ERR_SID); - sim->sim_domsid = sidstr; + /* Note: Free sim_domsid in smb_idmap_batch_destroy */ + sim->sim_domsid = smb_mem_strdup(sidstr); sim->sim_idtype = idtype; switch (idtype) { @@ -259,9 +269,6 @@ break; } - /* This was copied by idmap_get_Xbysid. */ - sim->sim_domsid = NULL; - return (stat); } @@ -272,6 +279,8 @@ * * sim->sim_domsid and sim->sim_rid will contain the mapping * result upon successful process of the batched request. + * Stash the type for error reporting (caller saves the ID). + * * NB: sim_domsid allocated by strdup, here or in libidmap */ idmap_stat @@ -284,6 +293,7 @@ if (!idmaph || !sim) return (IDMAP_ERR_ARG); + sim->sim_idtype = idtype; switch (idtype) { case SMB_IDMAP_USER: stat = idmap_get_sidbyuid(idmaph, id, flag, @@ -322,12 +332,35 @@ break; default: + ASSERT(0); return (IDMAP_ERR_ARG); } return (stat); } +static void +smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim) +{ + + if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) { + /* + * Note: The ID and type we asked idmap to map + * were saved in *sim_id and sim_idtype. + */ + uint_t id = (sim->sim_id == NULL) ? + 0 : (uint_t)*sim->sim_id; + cmn_err(CE_WARN, "Can't get SID for " + "ID=%u type=%d, status=%d", + id, sim->sim_idtype, sim->sim_stat); + } + + if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) { + cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d", + sim->sim_domsid, sim->sim_rid, sim->sim_stat); + } +} + /* * smb_idmap_batch_getmappings * @@ -353,13 +386,10 @@ */ for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) { if (sim->sim_stat != IDMAP_SUCCESS) { - if (sib->sib_flags == SMB_IDMAP_SID2ID) { - cmn_err(CE_NOTE, "[%d] %d (%d)", - sim->sim_idtype, - sim->sim_rid, - sim->sim_stat); + smb_idmap_bgm_report(sib, sim); + if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) { + return (sim->sim_stat); } - return (sim->sim_stat); } } @@ -389,6 +419,7 @@ sim = sib->sib_maps; for (i = 0; i < sib->sib_nmap; sim++, i++) { + ASSERT(sim->sim_domsid != NULL); if (sim->sim_domsid == NULL) return (-1); diff -r ebeeffcb370f -r 60e796757b53 usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Wed May 29 17:34:03 2019 +0000 +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Tue Jul 10 13:05:19 2018 -0400 @@ -21,7 +21,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. - * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #include @@ -129,6 +129,10 @@ * smb_token_sids2ids * * This will map all the SIDs of the access token to UIDs/GIDs. + * However, if there are some SIDs we can't map to UIDs/GIDs, + * we don't want to fail the logon, and instead just log the + * SIDs we could not map and continue as best we can. + * The flag SMB_IDMAP_SKIP_ERRS below does that. * * Returns 0 upon success. Otherwise, returns -1. */ @@ -148,7 +152,8 @@ else nmaps = token->tkn_win_grps.i_cnt + 3; - stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID); + stat = smb_idmap_batch_create(&sib, nmaps, + SMB_IDMAP_SID2ID | SMB_IDMAP_SKIP_ERRS); if (stat != IDMAP_SUCCESS) return (-1); diff -r ebeeffcb370f -r 60e796757b53 usr/src/lib/smbsrv/libsmb/common/smb_idmap.c --- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c Wed May 29 17:34:03 2019 +0000 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c Tue Jul 10 13:05:19 2018 -0400 @@ -20,17 +20,17 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * SMB server interface to idmap * (smb_idmap_get..., smb_idmap_batch_...) * - * There are three implementations of this interface: - * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod) - * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv) - * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb) + * There are three implementations of this interface. + * This is the libsmb version of these routines. See also: + * $SRC/uts/common/fs/smbsrv/smb_idmap.c + * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c * * There are enough differences (relative to the code size) * that it's more trouble than it's worth to merge them. @@ -197,6 +197,14 @@ smb_sid_free(sib->sib_maps[i].sim_sid); free(sib->sib_maps[i].sim_domsid); } + } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { + /* + * SID prefixes are allocated only when mapping + * SIDs to UID/GID + */ + for (i = 0; i < sib->sib_nmap; i++) { + free(sib->sib_maps[i].sim_domsid); + } } if (sib->sib_size && sib->sib_maps) { @@ -230,7 +238,8 @@ smb_sid_tostr(sid, sidstr); if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0) return (IDMAP_ERR_SID); - sim->sim_domsid = sidstr; + /* Note: Free sim_domsid in smb_idmap_batch_destroy */ + sim->sim_domsid = strdup(sidstr); sim->sim_idtype = idtype; switch (idtype) { @@ -258,9 +267,6 @@ break; } - /* This was copied by idmap_get_Xbysid. */ - sim->sim_domsid = NULL; - return (stat); } @@ -271,6 +277,8 @@ * * sim->sim_domsid and sim->sim_rid will contain the mapping * result upon successful process of the batched request. + * Stash the type for error reporting (caller saves the ID). + * * NB: sim_domsid allocated by strdup, here or in libidmap */ idmap_stat @@ -283,6 +291,7 @@ if (!idmaph || !sim) return (IDMAP_ERR_ARG); + sim->sim_idtype = idtype; switch (idtype) { case SMB_IDMAP_USER: stat = idmap_get_sidbyuid(idmaph, id, flag, @@ -327,6 +336,28 @@ return (stat); } +static void +smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim) +{ + + if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) { + /* + * Note: The ID and type we asked idmap to map + * were saved in *sim_id and sim_idtype. + */ + uint_t id = (sim->sim_id == NULL) ? + 0 : (uint_t)*sim->sim_id; + syslog(LOG_ERR, "Can't get SID for " + "ID=%u type=%d, status=%d", + id, sim->sim_idtype, sim->sim_stat); + } + + if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) { + syslog(LOG_ERR, "Can't get ID for SID %s-%u, status=%d", + sim->sim_domsid, sim->sim_rid, sim->sim_stat); + } +} + /* * smb_idmap_batch_getmappings * @@ -352,11 +383,10 @@ */ for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) { if (sim->sim_stat != IDMAP_SUCCESS) { - if (sib->sib_flags == SMB_IDMAP_SID2ID) { - smb_tracef("[%d] %d (%d)", sim->sim_idtype, - sim->sim_rid, sim->sim_stat); + smb_idmap_bgm_report(sib, sim); + if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) { + return (sim->sim_stat); } - return (sim->sim_stat); } } diff -r ebeeffcb370f -r 60e796757b53 usr/src/uts/common/fs/smbsrv/smb_idmap.c --- a/usr/src/uts/common/fs/smbsrv/smb_idmap.c Wed May 29 17:34:03 2019 +0000 +++ b/usr/src/uts/common/fs/smbsrv/smb_idmap.c Tue Jul 10 13:05:19 2018 -0400 @@ -20,24 +20,24 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * SMB server interface to idmap * (smb_idmap_get..., smb_idmap_batch_...) * - * There are three implementations of this interface: - * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod) - * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv) - * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb) + * There are three implementations of this interface. + * This is the kernel version of these routines. See also: + * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c + * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c * * There are enough differences (relative to the code size) * that it's more trouble than it's worth to merge them. * * This one differs from the others in that it: * calls kernel (kidmap_...) interfaces - * domain SIDs are shared, not strdup'ed + * returned domain SIDs are shared, not strdup'ed */ /* @@ -174,7 +174,7 @@ idmap_stat smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) { - ASSERT(sib); + ASSERT(sib != NULL); bzero(sib, sizeof (smb_idmap_batch_t)); @@ -201,11 +201,13 @@ char *domsid; int i; - ASSERT(sib); - ASSERT(sib->sib_maps); + ASSERT(sib != NULL); + ASSERT(sib->sib_maps != NULL); - if (sib->sib_idmaph) + if (sib->sib_idmaph) { kidmap_get_destroy(sib->sib_idmaph); + sib->sib_idmaph = NULL; + } if (sib->sib_flags & SMB_IDMAP_ID2SID) { /* @@ -226,8 +228,10 @@ } } - if (sib->sib_size && sib->sib_maps) + if (sib->sib_size && sib->sib_maps) { kmem_free(sib->sib_maps, sib->sib_size); + sib->sib_maps = NULL; + } } /* @@ -249,14 +253,16 @@ char strsid[SMB_SID_STRSZ]; idmap_stat idm_stat; - ASSERT(idmaph); - ASSERT(sim); - ASSERT(sid); + ASSERT(idmaph != NULL); + ASSERT(sim != NULL); + ASSERT(sid != NULL); smb_sid_tostr(sid, strsid); if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0) return (IDMAP_ERR_SID); + /* Note: Free sim_domsid in smb_idmap_batch_destroy */ sim->sim_domsid = smb_mem_strdup(strsid); + sim->sim_idtype = idtype; switch (idtype) { case SMB_IDMAP_USER: @@ -290,6 +296,7 @@ * * sim->sim_domsid and sim->sim_rid will contain the mapping * result upon successful process of the batched request. + * Stash the type for error reporting (caller saves the ID). */ idmap_stat smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, @@ -297,6 +304,7 @@ { idmap_stat idm_stat; + sim->sim_idtype = idtype; switch (idtype) { case SMB_IDMAP_USER: idm_stat = kidmap_batch_getsidbyuid(idmaph, id, @@ -342,6 +350,28 @@ return (idm_stat); } +static void +smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim) +{ + + if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) { + /* + * Note: The ID and type we asked idmap to map + * were saved in *sim_id and sim_idtype. + */ + uint_t id = (sim->sim_id == NULL) ? + 0 : (uint_t)*sim->sim_id; + cmn_err(CE_WARN, "Can't get SID for " + "ID=%u type=%d, status=%d", + id, sim->sim_idtype, sim->sim_stat); + } + + if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) { + cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d", + sim->sim_domsid, sim->sim_rid, sim->sim_stat); + } +} + /* * smb_idmap_batch_getmappings * @@ -356,6 +386,7 @@ smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) { idmap_stat idm_stat = IDMAP_SUCCESS; + smb_idmap_t *sim; int i; idm_stat = kidmap_get_mappings(sib->sib_idmaph); @@ -365,9 +396,13 @@ /* * Check the status for all the queued requests */ - for (i = 0; i < sib->sib_nmap; i++) { - if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) - return (sib->sib_maps[i].sim_stat); + for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) { + if (sim->sim_stat != IDMAP_SUCCESS) { + smb_idmap_bgm_report(sib, sim); + if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) { + return (sim->sim_stat); + } + } } if (smb_idmap_batch_binsid(sib) != 0) @@ -396,7 +431,7 @@ sim = sib->sib_maps; for (i = 0; i < sib->sib_nmap; sim++, i++) { - ASSERT(sim->sim_domsid); + ASSERT(sim->sim_domsid != NULL); if (sim->sim_domsid == NULL) return (1); diff -r ebeeffcb370f -r 60e796757b53 usr/src/uts/common/smbsrv/smb_idmap.h --- a/usr/src/uts/common/smbsrv/smb_idmap.h Wed May 29 17:34:03 2019 +0000 +++ b/usr/src/uts/common/smbsrv/smb_idmap.h Tue Jul 10 13:05:19 2018 -0400 @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SMB_IDMAP_H @@ -59,6 +59,7 @@ #define SMB_IDMAP_SID2ID 0x0001 #define SMB_IDMAP_ID2SID 0x0002 +#define SMB_IDMAP_SKIP_ERRS 0x0004 /* * smb_idmap_t @@ -79,8 +80,8 @@ uint16_t sib_nmap; uint32_t sib_flags; uint32_t sib_size; - smb_idmap_t *sib_maps; - idmap_get_handle_t *sib_idmaph; + smb_idmap_t *sib_maps; + idmap_get_handle_t *sib_idmaph; } smb_idmap_batch_t; idmap_stat smb_idmap_getsid(uid_t, int, smb_sid_t **);