1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * LSA lookups
  29  */
  30 
  31 #include <stdio.h>
  32 #include <note.h>
  33 #include <assert.h>
  34 
  35 #include "idmapd.h"
  36 #include "libsmb.h"
  37 
  38 idmap_retcode
  39 idmap_lsa_xlate_sid_type(const lsa_account_t *acct, idmap_id_type *ret_type)
  40 {
  41         switch (acct->a_sidtype) {
  42         case SidTypeUser:
  43         case SidTypeComputer:
  44         case SidTypeDomain:
  45         case SidTypeDeletedAccount:
  46         case SidTypeUnknown:
  47         case SidTypeLabel:
  48                 *ret_type = IDMAP_USID;
  49                 return (IDMAP_SUCCESS);
  50         case SidTypeGroup:
  51         case SidTypeAlias:
  52         case SidTypeWellKnownGroup:
  53                 *ret_type = IDMAP_GSID;
  54                 return (IDMAP_SUCCESS);
  55         case SidTypeNull:
  56         case SidTypeInvalid:
  57         default:
  58                 idmapdlog(LOG_WARNING,
  59                     "LSA lookup:  bad type %d for %s@%s",
  60                     acct->a_sidtype, acct->a_name, acct->a_domain);
  61                 return (IDMAP_ERR_OTHER);
  62         }
  63         NOTE(NOTREACHED)
  64 }
  65 
  66 /* Given SID, look up name and type */
  67 idmap_retcode
  68 lookup_lsa_by_sid(
  69     const char *sidprefix,
  70     uint32_t rid,
  71     char **ret_name,
  72     char **ret_domain,
  73     idmap_id_type *ret_type)
  74 {
  75         lsa_account_t acct;
  76         char sid[SMB_SID_STRSZ + 1];
  77         idmap_retcode ret;
  78         int rc;
  79 
  80         (void) memset(&acct, 0, sizeof (acct));
  81         *ret_name = NULL;
  82         *ret_domain = NULL;
  83 
  84         (void) snprintf(sid, sizeof (sid), "%s-%u", sidprefix, rid);
  85 
  86         rc = smb_lookup_sid(sid, &acct);
  87         if (rc != 0) {
  88                 idmapdlog(LOG_ERR, "Error:  smb_lookup_sid failed.");
  89                 idmapdlog(LOG_ERR,
  90                     "Check SMB service (svc:/network/smb/server).");
  91                 idmapdlog(LOG_ERR,
  92                     "Check connectivity to Active Directory.");
  93 
  94                 ret = IDMAP_ERR_OTHER;
  95                 goto out;
  96         }
  97         if (acct.a_status == NT_STATUS_NONE_MAPPED) {
  98                 ret = IDMAP_ERR_NOTFOUND;
  99                 goto out;
 100         }
 101         if (acct.a_status != NT_STATUS_SUCCESS) {
 102                 idmapdlog(LOG_WARNING,
 103                     "Warning:  smb_lookup_sid(%s) failed (0x%x)",
 104                     sid, acct.a_status);
 105                 /* Fail soft */
 106                 ret = IDMAP_ERR_NOTFOUND;
 107                 goto out;
 108         }
 109 
 110         ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
 111         if (ret != IDMAP_SUCCESS)
 112                 goto out;
 113 
 114         *ret_name = strdup(acct.a_name);
 115         if (*ret_name == NULL) {
 116                 ret = IDMAP_ERR_MEMORY;
 117                 goto out;
 118         }
 119 
 120         *ret_domain = strdup(acct.a_domain);
 121         if (*ret_domain == NULL) {
 122                 ret = IDMAP_ERR_MEMORY;
 123                 goto out;
 124         }
 125 
 126         ret = IDMAP_SUCCESS;
 127 
 128 out:
 129         if (ret != IDMAP_SUCCESS) {
 130                 free(*ret_name);
 131                 *ret_name = NULL;
 132                 free(*ret_domain);
 133                 *ret_domain = NULL;
 134         }
 135         return (ret);
 136 }
 137 
 138 /* Given name and optional domain, look up SID, type, and canonical name */
 139 idmap_retcode
 140 lookup_lsa_by_name(
 141     const char *name,
 142     const char *domain,
 143     char **ret_sidprefix,
 144     uint32_t *ret_rid,
 145     char **ret_name,
 146     char **ret_domain,
 147     idmap_id_type *ret_type)
 148 {
 149         lsa_account_t acct;
 150         char *namedom = NULL;
 151         idmap_retcode ret;
 152         int rc;
 153 
 154         (void) memset(&acct, 0, sizeof (acct));
 155         *ret_sidprefix = NULL;
 156         if (ret_name != NULL)
 157                 *ret_name = NULL;
 158         if (ret_domain != NULL)
 159                 *ret_domain = NULL;
 160 
 161         if (domain != NULL)
 162                 (void) asprintf(&namedom, "%s@%s", name, domain);
 163         else
 164                 namedom = strdup(name);
 165         if (namedom == NULL) {
 166                 ret = IDMAP_ERR_MEMORY;
 167                 goto out;
 168         }
 169 
 170         rc = smb_lookup_name(namedom, SidTypeUnknown, &acct);
 171         if (rc != 0) {
 172                 idmapdlog(LOG_ERR, "Error:  smb_lookup_name failed.");
 173                 idmapdlog(LOG_ERR,
 174                     "Check SMB service (svc:/network/smb/server).");
 175                 idmapdlog(LOG_ERR,
 176                     "Check connectivity to Active Directory.");
 177                 ret = IDMAP_ERR_OTHER;
 178                 goto out;
 179         }
 180         if (acct.a_status == NT_STATUS_NONE_MAPPED) {
 181                 ret = IDMAP_ERR_NOTFOUND;
 182                 goto out;
 183         }
 184         if (acct.a_status != NT_STATUS_SUCCESS) {
 185                 idmapdlog(LOG_WARNING,
 186                     "Warning:  smb_lookup_name(%s) failed (0x%x)",
 187                     namedom, acct.a_status);
 188                 /* Fail soft */
 189                 ret = IDMAP_ERR_NOTFOUND;
 190                 goto out;
 191         }
 192 
 193         rc = smb_sid_splitstr(acct.a_sid, ret_rid);
 194         assert(rc == 0);
 195         *ret_sidprefix = strdup(acct.a_sid);
 196         if (*ret_sidprefix == NULL) {
 197                 ret = IDMAP_ERR_MEMORY;
 198                 goto out;
 199         }
 200 
 201         ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
 202         if (ret != IDMAP_SUCCESS)
 203                 goto out;
 204 
 205         if (ret_name != NULL) {
 206                 *ret_name = strdup(acct.a_name);
 207                 if (*ret_name == NULL) {
 208                         ret = IDMAP_ERR_MEMORY;
 209                         goto out;
 210                 }
 211         }
 212 
 213         if (ret_domain != NULL) {
 214                 *ret_domain = strdup(acct.a_domain);
 215                 if (*ret_domain == NULL) {
 216                         ret = IDMAP_ERR_MEMORY;
 217                         goto out;
 218                 }
 219         }
 220 
 221         ret = IDMAP_SUCCESS;
 222 
 223 out:
 224         free(namedom);
 225         if (ret != IDMAP_SUCCESS) {
 226                 if (ret_name != NULL) {
 227                         free(*ret_name);
 228                         *ret_name = NULL;
 229                 }
 230                 if (ret_domain != NULL) {
 231                         free(*ret_domain);
 232                         *ret_domain = NULL;
 233                 }
 234                 free(*ret_sidprefix);
 235                 *ret_sidprefix = NULL;
 236         }
 237         return (ret);
 238 }
 239 
 240 /*
 241  * This exists just so we can avoid exposing all of idmapd to libsmb.h.
 242  * Like the above functions, it's a door call over to smbd.
 243  */
 244 void
 245 notify_dc_changed(void)
 246 {
 247         smb_notify_dc_changed();
 248 }