Print this page
NEX-17589 Get "too high" smbd error when copy big file to cifs share
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-17795 SMB logon should tolerate idmap problems
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2461 smb_split_sid uses wrong allocation size


   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  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * SMB server interface to idmap
  28  * (smb_idmap_get..., smb_idmap_batch_...)
  29  *
  30  * There are three implementations of this interface:
  31  *      uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
  32  *      lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
  33  *      lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
  34  *
  35  * There are enough differences (relative to the code size)
  36  * that it's more trouble than it's worth to merge them.
  37  *
  38  * This one differs from the others in that it:
  39  *      calls idmap interfaces (libidmap)
  40  *      domain SIDs returned are allocated
  41  */
  42 
  43 #include <syslog.h>
  44 #include <strings.h>
  45 #include <smbsrv/libsmb.h>
  46 
  47 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
  48 
  49 /*
  50  * Report an idmap error.
  51  */
  52 void
  53 smb_idmap_check(const char *s, idmap_stat stat)


 180         if (sib == NULL)
 181                 return;
 182 
 183         if (sib->sib_idmaph) {
 184                 idmap_get_destroy(sib->sib_idmaph);
 185                 sib->sib_idmaph = NULL;
 186         }
 187 
 188         if (sib->sib_maps == NULL)
 189                 return;
 190 
 191         if (sib->sib_flags & SMB_IDMAP_ID2SID) {
 192                 /*
 193                  * SIDs are allocated only when mapping
 194                  * UID/GID to SIDs
 195                  */
 196                 for (i = 0; i < sib->sib_nmap; i++) {
 197                         smb_sid_free(sib->sib_maps[i].sim_sid);
 198                         free(sib->sib_maps[i].sim_domsid);
 199                 }







 200         }

 201 
 202         if (sib->sib_size && sib->sib_maps) {
 203                 free(sib->sib_maps);
 204                 sib->sib_maps = NULL;
 205         }
 206 }
 207 
 208 /*
 209  * smb_idmap_batch_getid
 210  *
 211  * Queue a request to map the given SID to a UID or GID.
 212  *
 213  * sim->sim_id should point to variable that's supposed to
 214  * hold the returned UID/GID. This needs to be setup by caller
 215  * of this function.
 216  * If requested ID type is known, it's passed as 'idtype',
 217  * if it's unknown it'll be returned in sim->sim_idtype.
 218  */
 219 idmap_stat
 220 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 221     smb_sid_t *sid, int idtype)
 222 {
 223         char sidstr[SMB_SID_STRSZ];
 224         idmap_stat stat;
 225         int flag = 0;
 226 
 227         if (idmaph == NULL || sim == NULL || sid == NULL)
 228                 return (IDMAP_ERR_ARG);
 229 
 230         smb_sid_tostr(sid, sidstr);
 231         if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0)
 232                 return (IDMAP_ERR_SID);
 233         sim->sim_domsid = sidstr;

 234         sim->sim_idtype = idtype;
 235 
 236         switch (idtype) {
 237         case SMB_IDMAP_USER:
 238                 stat = idmap_get_uidbysid(idmaph, sim->sim_domsid,
 239                     sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
 240                 smb_idmap_check("idmap_get_uidbysid", stat);
 241                 break;
 242 
 243         case SMB_IDMAP_GROUP:
 244                 stat = idmap_get_gidbysid(idmaph, sim->sim_domsid,
 245                     sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
 246                 smb_idmap_check("idmap_get_gidbysid", stat);
 247                 break;
 248 
 249         case SMB_IDMAP_UNKNOWN:
 250                 stat = idmap_get_pidbysid(idmaph, sim->sim_domsid,
 251                     sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype,
 252                     &sim->sim_stat);
 253                 smb_idmap_check("idmap_get_pidbysid", stat);
 254                 break;
 255 
 256         default:
 257                 stat = IDMAP_ERR_ARG;
 258                 break;
 259         }
 260 
 261         /* This was copied by idmap_get_Xbysid. */
 262         sim->sim_domsid = NULL;
 263 
 264         return (stat);
 265 }
 266 
 267 /*
 268  * smb_idmap_batch_getsid
 269  *
 270  * Queue a request to map the given UID/GID to a SID.
 271  *
 272  * sim->sim_domsid and sim->sim_rid will contain the mapping
 273  * result upon successful process of the batched request.


 274  * NB: sim_domsid allocated by strdup, here or in libidmap
 275  */
 276 idmap_stat
 277 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 278     uid_t id, int idtype)
 279 {
 280         idmap_stat stat;
 281         int flag = 0;
 282 
 283         if (!idmaph || !sim)
 284                 return (IDMAP_ERR_ARG);
 285 

 286         switch (idtype) {
 287         case SMB_IDMAP_USER:
 288                 stat = idmap_get_sidbyuid(idmaph, id, flag,
 289                     &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
 290                 smb_idmap_check("idmap_get_sidbyuid", stat);
 291                 break;
 292 
 293         case SMB_IDMAP_GROUP:
 294                 stat = idmap_get_sidbygid(idmaph, id, flag,
 295                     &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
 296                 smb_idmap_check("idmap_get_sidbygid", stat);
 297                 break;
 298 
 299         case SMB_IDMAP_OWNERAT:
 300                 /* Current Owner S-1-5-32-766 */
 301                 sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
 302                 sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
 303                 sim->sim_stat = IDMAP_SUCCESS;
 304                 stat = IDMAP_SUCCESS;
 305                 break;


 310                 sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
 311                 sim->sim_stat = IDMAP_SUCCESS;
 312                 stat = IDMAP_SUCCESS;
 313                 break;
 314 
 315         case SMB_IDMAP_EVERYONE:
 316                 /* Everyone S-1-1-0 */
 317                 sim->sim_domsid = strdup(NT_WORLD_AUTH_SIDSTR);
 318                 sim->sim_rid = 0;
 319                 sim->sim_stat = IDMAP_SUCCESS;
 320                 stat = IDMAP_SUCCESS;
 321                 break;
 322 
 323         default:
 324                 return (IDMAP_ERR_ARG);
 325         }
 326 
 327         return (stat);
 328 }
 329 






















 330 /*
 331  * smb_idmap_batch_getmappings
 332  *
 333  * trigger ID mapping service to get the mappings for queued
 334  * requests.
 335  *
 336  * Checks the result of all the queued requests.
 337  */
 338 idmap_stat
 339 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
 340 {
 341         idmap_stat stat = IDMAP_SUCCESS;
 342         smb_idmap_t *sim;
 343         int i;
 344 
 345         if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) {
 346                 smb_idmap_check("idmap_get_mappings", stat);
 347                 return (stat);
 348         }
 349 
 350         /*
 351          * Check the status for all the queued requests
 352          */
 353         for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
 354                 if (sim->sim_stat != IDMAP_SUCCESS) {
 355                         if (sib->sib_flags == SMB_IDMAP_SID2ID) {
 356                                 smb_tracef("[%d] %d (%d)", sim->sim_idtype,
 357                                     sim->sim_rid, sim->sim_stat);
 358                         }
 359                         return (sim->sim_stat);
 360                 }
 361         }

 362 
 363         if (smb_idmap_batch_binsid(sib) != 0)
 364                 stat = IDMAP_ERR_OTHER;
 365 
 366         return (stat);
 367 }
 368 
 369 /*
 370  * smb_idmap_batch_binsid
 371  *
 372  * Convert sidrids to binary sids
 373  *
 374  * Returns 0 if successful and non-zero upon failure.
 375  */
 376 static int
 377 smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
 378 {
 379         smb_sid_t *sid;
 380         smb_idmap_t *sim;
 381         int i;


   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  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * SMB server interface to idmap
  28  * (smb_idmap_get..., smb_idmap_batch_...)
  29  *
  30  * There are three implementations of this interface.
  31  * This is the libsmb version of these routines.  See also:
  32  * $SRC/uts/common/fs/smbsrv/smb_idmap.c
  33  * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
  34  *
  35  * There are enough differences (relative to the code size)
  36  * that it's more trouble than it's worth to merge them.
  37  *
  38  * This one differs from the others in that it:
  39  *      calls idmap interfaces (libidmap)
  40  *      domain SIDs returned are allocated
  41  */
  42 
  43 #include <syslog.h>
  44 #include <strings.h>
  45 #include <smbsrv/libsmb.h>
  46 
  47 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
  48 
  49 /*
  50  * Report an idmap error.
  51  */
  52 void
  53 smb_idmap_check(const char *s, idmap_stat stat)


 180         if (sib == NULL)
 181                 return;
 182 
 183         if (sib->sib_idmaph) {
 184                 idmap_get_destroy(sib->sib_idmaph);
 185                 sib->sib_idmaph = NULL;
 186         }
 187 
 188         if (sib->sib_maps == NULL)
 189                 return;
 190 
 191         if (sib->sib_flags & SMB_IDMAP_ID2SID) {
 192                 /*
 193                  * SIDs are allocated only when mapping
 194                  * UID/GID to SIDs
 195                  */
 196                 for (i = 0; i < sib->sib_nmap; i++) {
 197                         smb_sid_free(sib->sib_maps[i].sim_sid);
 198                         free(sib->sib_maps[i].sim_domsid);
 199                 }
 200         } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
 201                 /*
 202                  * SID prefixes are allocated only when mapping
 203                  * SIDs to UID/GID
 204                  */
 205                 for (i = 0; i < sib->sib_nmap; i++) {
 206                         free(sib->sib_maps[i].sim_domsid);
 207                 }
 208         }
 209 
 210         if (sib->sib_size && sib->sib_maps) {
 211                 free(sib->sib_maps);
 212                 sib->sib_maps = NULL;
 213         }
 214 }
 215 
 216 /*
 217  * smb_idmap_batch_getid
 218  *
 219  * Queue a request to map the given SID to a UID or GID.
 220  *
 221  * sim->sim_id should point to variable that's supposed to
 222  * hold the returned UID/GID. This needs to be setup by caller
 223  * of this function.
 224  * If requested ID type is known, it's passed as 'idtype',
 225  * if it's unknown it'll be returned in sim->sim_idtype.
 226  */
 227 idmap_stat
 228 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 229     smb_sid_t *sid, int idtype)
 230 {
 231         char sidstr[SMB_SID_STRSZ];
 232         idmap_stat stat;
 233         int flag = 0;
 234 
 235         if (idmaph == NULL || sim == NULL || sid == NULL)
 236                 return (IDMAP_ERR_ARG);
 237 
 238         smb_sid_tostr(sid, sidstr);
 239         if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0)
 240                 return (IDMAP_ERR_SID);
 241         /* Note: Free sim_domsid in smb_idmap_batch_destroy */
 242         sim->sim_domsid = strdup(sidstr);
 243         sim->sim_idtype = idtype;
 244 
 245         switch (idtype) {
 246         case SMB_IDMAP_USER:
 247                 stat = idmap_get_uidbysid(idmaph, sim->sim_domsid,
 248                     sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
 249                 smb_idmap_check("idmap_get_uidbysid", stat);
 250                 break;
 251 
 252         case SMB_IDMAP_GROUP:
 253                 stat = idmap_get_gidbysid(idmaph, sim->sim_domsid,
 254                     sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
 255                 smb_idmap_check("idmap_get_gidbysid", stat);
 256                 break;
 257 
 258         case SMB_IDMAP_UNKNOWN:
 259                 stat = idmap_get_pidbysid(idmaph, sim->sim_domsid,
 260                     sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype,
 261                     &sim->sim_stat);
 262                 smb_idmap_check("idmap_get_pidbysid", stat);
 263                 break;
 264 
 265         default:
 266                 stat = IDMAP_ERR_ARG;
 267                 break;
 268         }
 269 



 270         return (stat);
 271 }
 272 
 273 /*
 274  * smb_idmap_batch_getsid
 275  *
 276  * Queue a request to map the given UID/GID to a SID.
 277  *
 278  * sim->sim_domsid and sim->sim_rid will contain the mapping
 279  * result upon successful process of the batched request.
 280  * Stash the type for error reporting (caller saves the ID).
 281  *
 282  * NB: sim_domsid allocated by strdup, here or in libidmap
 283  */
 284 idmap_stat
 285 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 286     uid_t id, int idtype)
 287 {
 288         idmap_stat stat;
 289         int flag = 0;
 290 
 291         if (!idmaph || !sim)
 292                 return (IDMAP_ERR_ARG);
 293 
 294         sim->sim_idtype = idtype;
 295         switch (idtype) {
 296         case SMB_IDMAP_USER:
 297                 stat = idmap_get_sidbyuid(idmaph, id, flag,
 298                     &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
 299                 smb_idmap_check("idmap_get_sidbyuid", stat);
 300                 break;
 301 
 302         case SMB_IDMAP_GROUP:
 303                 stat = idmap_get_sidbygid(idmaph, id, flag,
 304                     &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
 305                 smb_idmap_check("idmap_get_sidbygid", stat);
 306                 break;
 307 
 308         case SMB_IDMAP_OWNERAT:
 309                 /* Current Owner S-1-5-32-766 */
 310                 sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
 311                 sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
 312                 sim->sim_stat = IDMAP_SUCCESS;
 313                 stat = IDMAP_SUCCESS;
 314                 break;


 319                 sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
 320                 sim->sim_stat = IDMAP_SUCCESS;
 321                 stat = IDMAP_SUCCESS;
 322                 break;
 323 
 324         case SMB_IDMAP_EVERYONE:
 325                 /* Everyone S-1-1-0 */
 326                 sim->sim_domsid = strdup(NT_WORLD_AUTH_SIDSTR);
 327                 sim->sim_rid = 0;
 328                 sim->sim_stat = IDMAP_SUCCESS;
 329                 stat = IDMAP_SUCCESS;
 330                 break;
 331 
 332         default:
 333                 return (IDMAP_ERR_ARG);
 334         }
 335 
 336         return (stat);
 337 }
 338 
 339 static void
 340 smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim)
 341 {
 342 
 343         if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
 344                 /*
 345                  * Note: The ID and type we asked idmap to map
 346                  * were saved in *sim_id and sim_idtype.
 347                  */
 348                 uint_t id = (sim->sim_id == NULL) ?
 349                     0 : (uint_t)*sim->sim_id;
 350                 syslog(LOG_ERR, "Can't get SID for "
 351                     "ID=%u type=%d, status=%d",
 352                     id, sim->sim_idtype, sim->sim_stat);
 353         }
 354 
 355         if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
 356                 syslog(LOG_ERR, "Can't get ID for SID %s-%u, status=%d",
 357                     sim->sim_domsid, sim->sim_rid, sim->sim_stat);
 358         }
 359 }
 360 
 361 /*
 362  * smb_idmap_batch_getmappings
 363  *
 364  * trigger ID mapping service to get the mappings for queued
 365  * requests.
 366  *
 367  * Checks the result of all the queued requests.
 368  */
 369 idmap_stat
 370 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
 371 {
 372         idmap_stat stat = IDMAP_SUCCESS;
 373         smb_idmap_t *sim;
 374         int i;
 375 
 376         if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) {
 377                 smb_idmap_check("idmap_get_mappings", stat);
 378                 return (stat);
 379         }
 380 
 381         /*
 382          * Check the status for all the queued requests
 383          */
 384         for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
 385                 if (sim->sim_stat != IDMAP_SUCCESS) {
 386                         smb_idmap_bgm_report(sib, sim);
 387                         if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) {


 388                                 return (sim->sim_stat);
 389                         }
 390                 }
 391         }
 392 
 393         if (smb_idmap_batch_binsid(sib) != 0)
 394                 stat = IDMAP_ERR_OTHER;
 395 
 396         return (stat);
 397 }
 398 
 399 /*
 400  * smb_idmap_batch_binsid
 401  *
 402  * Convert sidrids to binary sids
 403  *
 404  * Returns 0 if successful and non-zero upon failure.
 405  */
 406 static int
 407 smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
 408 {
 409         smb_sid_t *sid;
 410         smb_idmap_t *sim;
 411         int i;