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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 /* 32 * Copyright (c) 2013 RackTop Systems. 33 */ 34 35 /*LINTLIBRARY*/ 36 37 #include <sys/types.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <userdefs.h> 41 #include <user_attr.h> 42 #include <limits.h> 43 #include <stdlib.h> 44 #include <stddef.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include "userdisp.h" 48 #include "funcs.h" 49 #include "messages.h" 50 51 /* Print out a NL when the line gets too long */ 52 #define PRINTNL() \ 53 if (outcount > 40) { \ 54 outcount = 0; \ 55 (void) fprintf(fptr, "\n"); \ 56 } 57 58 #define SKIPWS(ptr) while (*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++ 59 60 static char *dup_to_nl(char *); 61 62 static struct userdefs defaults = { 63 DEFRID, DEFGROUP, DEFGNAME, DEFPARENT, DEFSKL, 64 DEFSHL, DEFINACT, DEFEXPIRE, DEFAUTH, DEFPROF, 65 DEFROLE, DEFPROJ, DEFPROJNAME, DEFLIMPRIV, 66 DEFDFLTPRIV, DEFLOCK_AFTER_RETRIES 67 }; 68 69 #define INT 0 70 #define STR 1 71 #define PROJID 2 72 73 #define DEFOFF(field) offsetof(struct userdefs, field) 74 #define FIELD(up, pe, type) (*(type *)((char *)(up) + (pe)->off)) 75 76 typedef struct parsent { 77 const char *name; /* deffoo= */ 78 const size_t nmsz; /* length of def= string (excluding \0) */ 79 const int type; /* type of entry */ 80 const ptrdiff_t off; /* offset in userdefs structure */ 81 const char *uakey; /* user_attr key, if defined */ 82 } parsent_t; 83 84 static const parsent_t tab[] = { 85 { GIDSTR, sizeof (GIDSTR) - 1, INT, DEFOFF(defgroup) }, 86 { GNAMSTR, sizeof (GNAMSTR) - 1, STR, DEFOFF(defgname) }, 87 { PARSTR, sizeof (PARSTR) - 1, STR, DEFOFF(defparent) }, 88 { SKLSTR, sizeof (SKLSTR) - 1, STR, DEFOFF(defskel) }, 89 { SHELLSTR, sizeof (SHELLSTR) - 1, STR, DEFOFF(defshell) }, 90 { INACTSTR, sizeof (INACTSTR) - 1, INT, DEFOFF(definact) }, 91 { EXPIRESTR, sizeof (EXPIRESTR) - 1, STR, DEFOFF(defexpire) }, 92 { AUTHSTR, sizeof (AUTHSTR) - 1, STR, DEFOFF(defauth), 93 USERATTR_AUTHS_KW }, 94 { ROLESTR, sizeof (ROLESTR) - 1, STR, DEFOFF(defrole), 95 USERATTR_ROLES_KW }, 96 { PROFSTR, sizeof (PROFSTR) - 1, STR, DEFOFF(defprof), 97 USERATTR_PROFILES_KW }, 98 { PROJSTR, sizeof (PROJSTR) - 1, PROJID, DEFOFF(defproj) }, 99 { PROJNMSTR, sizeof (PROJNMSTR) - 1, STR, DEFOFF(defprojname) }, 100 { LIMPRSTR, sizeof (LIMPRSTR) - 1, STR, DEFOFF(deflimpriv), 101 USERATTR_LIMPRIV_KW }, 102 { DFLTPRSTR, sizeof (DFLTPRSTR) - 1, STR, DEFOFF(defdfltpriv), 103 USERATTR_DFLTPRIV_KW }, 104 { LOCK_AFTER_RETRIESSTR, sizeof (LOCK_AFTER_RETRIESSTR) - 1, 105 STR, DEFOFF(deflock_after_retries), 106 USERATTR_LOCK_AFTER_RETRIES_KW }, 107 }; 108 109 #define NDEF (sizeof (tab) / sizeof (parsent_t)) 110 111 FILE *defptr; /* default file - fptr */ 112 113 static const parsent_t * 114 scan(char **start_p) 115 { 116 static int ind = NDEF - 1; 117 char *cur_p = *start_p; 118 int lastind = ind; 119 120 if (!*cur_p || *cur_p == '\n' || *cur_p == '#') 121 return (NULL); 122 123 /* 124 * The magic in this loop is remembering the last index when 125 * reentering the function; the entries above are also used to 126 * order the output to the default file. 127 */ 128 do { 129 ind++; 130 ind %= NDEF; 131 132 if (strncmp(cur_p, tab[ind].name, tab[ind].nmsz) == 0) { 133 *start_p = cur_p + tab[ind].nmsz; 134 return (&tab[ind]); 135 } 136 } while (ind != lastind); 137 138 return (NULL); 139 } 140 141 /* 142 * getusrdef - access the user defaults file. If it doesn't exist, 143 * then returns default values of (values in userdefs.h): 144 * defrid = 100 145 * defgroup = 1 146 * defgname = other 147 * defparent = /home 148 * defskel = /usr/sadm/skel 149 * defshell = /bin/sh 150 * definact = 0 151 * defexpire = 0 152 * defauth = 0 153 * defprof = 0 154 * defrole = 0 155 * 156 * If getusrdef() is unable to access the defaults file, it 157 * returns a NULL pointer. 158 * 159 * If user defaults file exists, then getusrdef uses values 160 * in it to override the above values. 161 */ 162 163 struct userdefs * 164 getusrdef(char *usertype) 165 { 166 char instr[512], *ptr; 167 const parsent_t *pe; 168 169 if (is_role(usertype)) { 170 if ((defptr = fopen(DEFROLEFILE, "r")) == NULL) { 171 defaults.defshell = DEFROLESHL; 172 defaults.defprof = DEFROLEPROF; 173 return (&defaults); 174 } 175 } else { 176 if ((defptr = fopen(DEFFILE, "r")) == NULL) 177 return (&defaults); 178 } 179 180 while (fgets(instr, sizeof (instr), defptr) != NULL) { 181 ptr = instr; 182 183 SKIPWS(ptr); 184 185 if (*ptr == '#') 186 continue; 187 188 pe = scan(&ptr); 189 190 if (pe != NULL) { 191 switch (pe->type) { 192 case INT: 193 FIELD(&defaults, pe, int) = 194 (int)strtol(ptr, NULL, 10); 195 break; 196 case PROJID: 197 FIELD(&defaults, pe, projid_t) = 198 (projid_t)strtol(ptr, NULL, 10); 199 break; 200 case STR: 201 FIELD(&defaults, pe, char *) = dup_to_nl(ptr); 202 break; 203 } 204 } 205 } 206 207 (void) fclose(defptr); 208 209 return (&defaults); 210 } 211 212 static char * 213 dup_to_nl(char *from) 214 { 215 char *res = strdup(from); 216 217 char *p = strchr(res, '\n'); 218 if (p) 219 *p = '\0'; 220 221 return (res); 222 } 223 224 void 225 dispusrdef(FILE *fptr, unsigned flags, char *usertype) 226 { 227 struct userdefs *deflts = getusrdef(usertype); 228 int outcount = 0; 229 230 /* Print out values */ 231 232 if (flags & D_GROUP) { 233 outcount += fprintf(fptr, "group=%s,%ld ", 234 deflts->defgname, deflts->defgroup); 235 PRINTNL(); 236 } 237 238 if (flags & D_PROJ) { 239 outcount += fprintf(fptr, "project=%s,%ld ", 240 deflts->defprojname, deflts->defproj); 241 PRINTNL(); 242 } 243 244 if (flags & D_BASEDIR) { 245 outcount += fprintf(fptr, "basedir=%s ", deflts->defparent); 246 PRINTNL(); 247 } 248 249 if (flags & D_RID) { 250 outcount += fprintf(fptr, "rid=%ld ", deflts->defrid); 251 PRINTNL(); 252 } 253 254 if (flags & D_SKEL) { 255 outcount += fprintf(fptr, "skel=%s ", deflts->defskel); 256 PRINTNL(); 257 } 258 259 if (flags & D_SHELL) { 260 outcount += fprintf(fptr, "shell=%s ", deflts->defshell); 261 PRINTNL(); 262 } 263 264 if (flags & D_INACT) { 265 outcount += fprintf(fptr, "inactive=%d ", deflts->definact); 266 PRINTNL(); 267 } 268 269 if (flags & D_EXPIRE) { 270 outcount += fprintf(fptr, "expire=%s ", deflts->defexpire); 271 PRINTNL(); 272 } 273 274 if (flags & D_AUTH) { 275 outcount += fprintf(fptr, "auths=%s ", deflts->defauth); 276 PRINTNL(); 277 } 278 279 if (flags & D_PROF) { 280 outcount += fprintf(fptr, "profiles=%s ", deflts->defprof); 281 PRINTNL(); 282 } 283 284 if ((flags & D_ROLE) && 285 (!is_role(usertype))) { 286 outcount += fprintf(fptr, "roles=%s ", deflts->defrole); 287 PRINTNL(); 288 } 289 290 if (flags & D_LPRIV) { 291 outcount += fprintf(fptr, "limitpriv=%s ", 292 deflts->deflimpriv); 293 PRINTNL(); 294 } 295 296 if (flags & D_DPRIV) { 297 outcount += fprintf(fptr, "defaultpriv=%s ", 298 deflts->defdfltpriv); 299 PRINTNL(); 300 } 301 302 if (flags & D_LOCK) { 303 outcount += fprintf(fptr, "lock_after_retries=%s ", 304 deflts->deflock_after_retries); 305 } 306 307 if (outcount > 0) 308 (void) fprintf(fptr, "\n"); 309 } 310 311 /* 312 * putusrdef - 313 * changes default values in defadduser file 314 */ 315 int 316 putusrdef(struct userdefs *defs, char *usertype) 317 { 318 time_t timeval; /* time value from time */ 319 int i; 320 ptrdiff_t skip; 321 char *hdr; 322 323 /* 324 * file format is: 325 * #<tab>Default values for adduser. Changed mm/dd/yy hh:mm:ss. 326 * defgroup=m (m=default group id) 327 * defgname=str1 (str1=default group name) 328 * defparent=str2 (str2=default base directory) 329 * definactive=x (x=default inactive) 330 * defexpire=y (y=default expire) 331 * defproj=z (z=numeric project id) 332 * defprojname=str3 (str3=default project name) 333 * ... etc ... 334 */ 335 336 if (is_role(usertype)) { 337 if ((defptr = fopen(DEFROLEFILE, "w")) == NULL) { 338 errmsg(M_FAILED); 339 return (EX_UPDATE); 340 } 341 } else { 342 if ((defptr = fopen(DEFFILE, "w")) == NULL) { 343 errmsg(M_FAILED); 344 return (EX_UPDATE); 345 } 346 } 347 348 if (lockf(fileno(defptr), F_LOCK, 0) != 0) { 349 /* print error if can't lock whole of DEFFILE */ 350 errmsg(M_UPDATE, "created"); 351 return (EX_UPDATE); 352 } 353 354 if (is_role(usertype)) { 355 /* If it's a role, we must skip the defrole field */ 356 skip = offsetof(struct userdefs, defrole); 357 hdr = FHEADER_ROLE; 358 } else { 359 skip = -1; 360 hdr = FHEADER; 361 } 362 363 /* get time */ 364 timeval = time(NULL); 365 366 /* write it to file */ 367 if (fprintf(defptr, "%s%s\n", hdr, ctime(&timeval)) <= 0) { 368 errmsg(M_UPDATE, "created"); 369 return (EX_UPDATE); 370 } 371 372 for (i = 0; i < NDEF; i++) { 373 int res = 0; 374 375 if (tab[i].off == skip) 376 continue; 377 378 switch (tab[i].type) { 379 case INT: 380 res = fprintf(defptr, "%s%d\n", tab[i].name, 381 FIELD(defs, &tab[i], int)); 382 break; 383 case STR: 384 res = fprintf(defptr, "%s%s\n", tab[i].name, 385 FIELD(defs, &tab[i], char *)); 386 break; 387 case PROJID: 388 res = fprintf(defptr, "%s%d\n", tab[i].name, 389 (int)FIELD(defs, &tab[i], projid_t)); 390 break; 391 } 392 393 if (res <= 0) { 394 errmsg(M_UPDATE, "created"); 395 return (EX_UPDATE); 396 } 397 } 398 399 (void) lockf(fileno(defptr), F_ULOCK, 0); 400 (void) fclose(defptr); 401 402 return (EX_SUCCESS); 403 } 404 405 /* Export command line keys to defaults for useradd -D */ 406 void 407 update_def(struct userdefs *ud) 408 { 409 int i; 410 411 for (i = 0; i < NDEF; i++) { 412 char *val; 413 if (tab[i].uakey != NULL && 414 (val = getsetdefval(tab[i].uakey, NULL)) != NULL) 415 FIELD(ud, &tab[i], char *) = val; 416 } 417 } 418 419 /* Import default keys for ordinary useradd */ 420 void 421 import_def(struct userdefs *ud) 422 { 423 int i; 424 425 for (i = 0; i < NDEF; i++) { 426 if (tab[i].uakey != NULL && tab[i].type == STR) { 427 char *val = FIELD(ud, &tab[i], char *); 428 if (val == getsetdefval(tab[i].uakey, val)) 429 nkeys ++; 430 } 431 } 432 } 433