10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52657Srica * Common Development and Distribution License (the "License"). 62657Srica * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*12582SGlenn.Faden@Sun.COM * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate #include <stdio.h> 260Sstevel@tonic-gate #include <stdlib.h> 270Sstevel@tonic-gate #include <strings.h> 280Sstevel@tonic-gate #include <auth_attr.h> 290Sstevel@tonic-gate #include <prof_attr.h> 300Sstevel@tonic-gate #include <user_attr.h> 310Sstevel@tonic-gate #include <project.h> 320Sstevel@tonic-gate #include <secdb.h> 330Sstevel@tonic-gate #include <pwd.h> 340Sstevel@tonic-gate #include <unistd.h> 350Sstevel@tonic-gate #include <priv.h> 360Sstevel@tonic-gate #include <errno.h> 372657Srica #include <ctype.h> 382657Srica #include <tsol/label.h> 390Sstevel@tonic-gate #include "funcs.h" 400Sstevel@tonic-gate #include "messages.h" 410Sstevel@tonic-gate #include "userdefs.h" 420Sstevel@tonic-gate 430Sstevel@tonic-gate typedef struct ua_key { 440Sstevel@tonic-gate const char *key; 450Sstevel@tonic-gate const char *(*check)(const char *); 460Sstevel@tonic-gate const char *errstr; 470Sstevel@tonic-gate char *newvalue; 480Sstevel@tonic-gate } ua_key_t; 490Sstevel@tonic-gate 500Sstevel@tonic-gate static const char role[] = "role name"; 510Sstevel@tonic-gate static const char prof[] = "profile name"; 520Sstevel@tonic-gate static const char proj[] = "project name"; 530Sstevel@tonic-gate static const char priv[] = "privilege set"; 540Sstevel@tonic-gate static const char auth[] = "authorization"; 550Sstevel@tonic-gate static const char type[] = "user type"; 560Sstevel@tonic-gate static const char lock[] = "lock_after_retries value"; 572657Srica static const char label[] = "label"; 582657Srica static const char idlecmd[] = "idlecmd value"; 592657Srica static const char idletime[] = "idletime value"; 600Sstevel@tonic-gate 610Sstevel@tonic-gate 620Sstevel@tonic-gate static const char *check_auth(const char *); 630Sstevel@tonic-gate static const char *check_prof(const char *); 640Sstevel@tonic-gate static const char *check_role(const char *); 650Sstevel@tonic-gate static const char *check_proj(const char *); 660Sstevel@tonic-gate static const char *check_privset(const char *); 670Sstevel@tonic-gate static const char *check_type(const char *); 680Sstevel@tonic-gate static const char *check_lock_after_retries(const char *); 692657Srica static const char *check_label(const char *); 702657Srica static const char *check_idlecmd(const char *); 712657Srica static const char *check_idletime(const char *); 720Sstevel@tonic-gate 730Sstevel@tonic-gate int nkeys; 740Sstevel@tonic-gate 750Sstevel@tonic-gate static ua_key_t keys[] = { 760Sstevel@tonic-gate /* First entry is always set correctly in main() */ 770Sstevel@tonic-gate { USERATTR_TYPE_KW, check_type, type }, 780Sstevel@tonic-gate { USERATTR_AUTHS_KW, check_auth, auth }, 790Sstevel@tonic-gate { USERATTR_PROFILES_KW, check_prof, prof }, 800Sstevel@tonic-gate { USERATTR_ROLES_KW, check_role, role }, 810Sstevel@tonic-gate { USERATTR_DEFAULTPROJ_KW, check_proj, proj }, 820Sstevel@tonic-gate { USERATTR_LIMPRIV_KW, check_privset, priv }, 830Sstevel@tonic-gate { USERATTR_DFLTPRIV_KW, check_privset, priv }, 840Sstevel@tonic-gate { USERATTR_LOCK_AFTER_RETRIES_KW, check_lock_after_retries, lock }, 852657Srica { USERATTR_CLEARANCE, check_label, label }, 862657Srica { USERATTR_MINLABEL, check_label, label }, 872657Srica { USERATTR_IDLECMD_KW, check_idlecmd, idlecmd }, 882657Srica { USERATTR_IDLETIME_KW, check_idletime, idletime }, 890Sstevel@tonic-gate }; 900Sstevel@tonic-gate 910Sstevel@tonic-gate #define NKEYS (sizeof (keys)/sizeof (ua_key_t)) 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * Change a key, there are three different call sequences: 950Sstevel@tonic-gate * 960Sstevel@tonic-gate * key, value - key with option letter, value. 970Sstevel@tonic-gate * NULL, value - -K key=value option. 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate 1000Sstevel@tonic-gate void 1010Sstevel@tonic-gate change_key(const char *key, char *value) 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate int i; 1040Sstevel@tonic-gate const char *res; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate if (key == NULL) { 1070Sstevel@tonic-gate key = value; 1080Sstevel@tonic-gate value = strchr(value, '='); 1090Sstevel@tonic-gate /* Bad value */ 1100Sstevel@tonic-gate if (value == NULL) { 1110Sstevel@tonic-gate errmsg(M_INVALID_VALUE); 1120Sstevel@tonic-gate exit(EX_BADARG); 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate *value++ = '\0'; 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate for (i = 0; i < NKEYS; i++) { 1180Sstevel@tonic-gate if (strcmp(key, keys[i].key) == 0) { 1190Sstevel@tonic-gate if (keys[i].newvalue != NULL) { 1200Sstevel@tonic-gate /* Can't set a value twice */ 1210Sstevel@tonic-gate errmsg(M_REDEFINED_KEY, key); 1220Sstevel@tonic-gate exit(EX_BADARG); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate if (keys[i].check != NULL && 1260Sstevel@tonic-gate (res = keys[i].check(value)) != NULL) { 1270Sstevel@tonic-gate errmsg(M_INVALID, res, keys[i].errstr); 1280Sstevel@tonic-gate exit(EX_BADARG); 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate keys[i].newvalue = value; 1310Sstevel@tonic-gate nkeys++; 1320Sstevel@tonic-gate return; 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate errmsg(M_INVALID_KEY, key); 1360Sstevel@tonic-gate exit(EX_BADARG); 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * Add the keys to the argument vector. 1410Sstevel@tonic-gate */ 1420Sstevel@tonic-gate void 1430Sstevel@tonic-gate addkey_args(char **argv, int *index) 1440Sstevel@tonic-gate { 1450Sstevel@tonic-gate int i; 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate for (i = 0; i < NKEYS; i++) { 1480Sstevel@tonic-gate const char *key = keys[i].key; 1490Sstevel@tonic-gate char *val = keys[i].newvalue; 1500Sstevel@tonic-gate size_t len; 1510Sstevel@tonic-gate char *arg; 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate if (val == NULL) 1540Sstevel@tonic-gate continue; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate len = strlen(key) + strlen(val) + 2; 1570Sstevel@tonic-gate arg = malloc(len); 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate (void) snprintf(arg, len, "%s=%s", key, val); 1600Sstevel@tonic-gate argv[(*index)++] = "-K"; 1610Sstevel@tonic-gate argv[(*index)++] = arg; 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate /* 1660Sstevel@tonic-gate * Propose a default value for a key and get the actual value back. 1670Sstevel@tonic-gate * If the proposed default value is NULL, return the actual value set. 1680Sstevel@tonic-gate * The key argument is the user_attr key. 1690Sstevel@tonic-gate */ 1700Sstevel@tonic-gate char * 1710Sstevel@tonic-gate getsetdefval(const char *key, char *dflt) 1720Sstevel@tonic-gate { 1730Sstevel@tonic-gate int i; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate for (i = 0; i < NKEYS; i++) 1760Sstevel@tonic-gate if (strcmp(keys[i].key, key) == 0) 1770Sstevel@tonic-gate if (keys[i].newvalue != NULL) 1780Sstevel@tonic-gate return (keys[i].newvalue); 1790Sstevel@tonic-gate else 1800Sstevel@tonic-gate return (keys[i].newvalue = dflt); 1810Sstevel@tonic-gate return (NULL); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate char * 1850Sstevel@tonic-gate getusertype(char *cmdname) 1860Sstevel@tonic-gate { 1870Sstevel@tonic-gate static char usertype[MAX_TYPE_LENGTH]; 1880Sstevel@tonic-gate char *cmd; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if (cmd = strrchr(cmdname, '/')) 1910Sstevel@tonic-gate ++cmd; 1920Sstevel@tonic-gate else 1930Sstevel@tonic-gate cmd = cmdname; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* get user type based on the program name */ 1960Sstevel@tonic-gate if (strncmp(cmd, CMD_PREFIX_USER, 1970Sstevel@tonic-gate strlen(CMD_PREFIX_USER)) == 0) 1980Sstevel@tonic-gate strcpy(usertype, USERATTR_TYPE_NORMAL_KW); 1990Sstevel@tonic-gate else 2000Sstevel@tonic-gate strcpy(usertype, USERATTR_TYPE_NONADMIN_KW); 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate return (usertype); 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate int 2060Sstevel@tonic-gate is_role(char *usertype) 2070Sstevel@tonic-gate { 2080Sstevel@tonic-gate if (strcmp(usertype, USERATTR_TYPE_NONADMIN_KW) == 0) 2090Sstevel@tonic-gate return (1); 2100Sstevel@tonic-gate /* not a role */ 2110Sstevel@tonic-gate return (0); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * Verifies the provided list of authorizations are all valid. 2160Sstevel@tonic-gate * 2170Sstevel@tonic-gate * Returns NULL if all authorization names are valid. 2180Sstevel@tonic-gate * Otherwise, returns the invalid authorization name 2190Sstevel@tonic-gate * 2200Sstevel@tonic-gate */ 2210Sstevel@tonic-gate static const char * 2220Sstevel@tonic-gate check_auth(const char *auths) 2230Sstevel@tonic-gate { 2240Sstevel@tonic-gate char *authname; 2250Sstevel@tonic-gate authattr_t *result; 2260Sstevel@tonic-gate char *tmp; 2270Sstevel@tonic-gate struct passwd *pw; 2280Sstevel@tonic-gate int have_grant = 0; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate tmp = strdup(auths); 23112578SGlenn.Faden@Sun.COM if (tmp == NULL) { 23212578SGlenn.Faden@Sun.COM errmsg(M_NOSPACE); 23312578SGlenn.Faden@Sun.COM exit(EX_FAILURE); 23412578SGlenn.Faden@Sun.COM } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate authname = strtok(tmp, AUTH_SEP); 2370Sstevel@tonic-gate pw = getpwuid(getuid()); 2380Sstevel@tonic-gate if (pw == NULL) { 2390Sstevel@tonic-gate return (authname); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate while (authname != NULL) { 2430Sstevel@tonic-gate char *suffix; 2440Sstevel@tonic-gate char *authtoks; 2450Sstevel@tonic-gate 24612578SGlenn.Faden@Sun.COM /* Check if user has been granted this authorization */ 24712578SGlenn.Faden@Sun.COM if (!chkauthattr(authname, pw->pw_name)) 24812578SGlenn.Faden@Sun.COM return (authname); 24912578SGlenn.Faden@Sun.COM 25012578SGlenn.Faden@Sun.COM /* Remove named object after slash */ 25112578SGlenn.Faden@Sun.COM if ((suffix = index(authname, KV_OBJECTCHAR)) != NULL) 25212578SGlenn.Faden@Sun.COM *suffix = '\0'; 25312578SGlenn.Faden@Sun.COM 2540Sstevel@tonic-gate /* Find the suffix */ 2550Sstevel@tonic-gate if ((suffix = rindex(authname, '.')) == NULL) 2560Sstevel@tonic-gate return (authname); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate /* Check for existence in auth_attr */ 2590Sstevel@tonic-gate suffix++; 2600Sstevel@tonic-gate if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */ 2610Sstevel@tonic-gate result = getauthnam(authname); 2620Sstevel@tonic-gate if (result == NULL) { 2630Sstevel@tonic-gate /* can't find the auth */ 2640Sstevel@tonic-gate free_authattr(result); 2650Sstevel@tonic-gate return (authname); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate free_authattr(result); 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* Check if user can delegate this authorization */ 2710Sstevel@tonic-gate if (strcmp(suffix, "grant")) { /* Not a grant option */ 2720Sstevel@tonic-gate authtoks = malloc(strlen(authname) + sizeof ("grant")); 2730Sstevel@tonic-gate strcpy(authtoks, authname); 2740Sstevel@tonic-gate have_grant = 0; 2750Sstevel@tonic-gate while ((suffix = rindex(authtoks, '.')) && 2760Sstevel@tonic-gate !have_grant) { 2770Sstevel@tonic-gate strcpy(suffix, ".grant"); 2780Sstevel@tonic-gate if (chkauthattr(authtoks, pw->pw_name)) 2790Sstevel@tonic-gate have_grant = 1; 2800Sstevel@tonic-gate else 2810Sstevel@tonic-gate *suffix = '\0'; 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate if (!have_grant) 2840Sstevel@tonic-gate return (authname); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate authname = strtok(NULL, AUTH_SEP); 2870Sstevel@tonic-gate } 28812578SGlenn.Faden@Sun.COM free(tmp); 2890Sstevel@tonic-gate return (NULL); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Verifies the provided list of profile names are valid. 2940Sstevel@tonic-gate * 2950Sstevel@tonic-gate * Returns NULL if all profile names are valid. 2960Sstevel@tonic-gate * Otherwise, returns the invalid profile name 2970Sstevel@tonic-gate * 2980Sstevel@tonic-gate */ 2990Sstevel@tonic-gate static const char * 3000Sstevel@tonic-gate check_prof(const char *profs) 3010Sstevel@tonic-gate { 3020Sstevel@tonic-gate char *profname; 3030Sstevel@tonic-gate profattr_t *result; 3040Sstevel@tonic-gate char *tmp; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate tmp = strdup(profs); 30712578SGlenn.Faden@Sun.COM if (tmp == NULL) { 30812578SGlenn.Faden@Sun.COM errmsg(M_NOSPACE); 30912578SGlenn.Faden@Sun.COM exit(EX_FAILURE); 31012578SGlenn.Faden@Sun.COM } 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate profname = strtok(tmp, PROF_SEP); 3130Sstevel@tonic-gate while (profname != NULL) { 3140Sstevel@tonic-gate result = getprofnam(profname); 3150Sstevel@tonic-gate if (result == NULL) { 3160Sstevel@tonic-gate /* can't find the profile */ 3170Sstevel@tonic-gate return (profname); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate free_profattr(result); 3200Sstevel@tonic-gate profname = strtok(NULL, PROF_SEP); 3210Sstevel@tonic-gate } 32212578SGlenn.Faden@Sun.COM free(tmp); 3230Sstevel@tonic-gate return (NULL); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /* 3280Sstevel@tonic-gate * Verifies the provided list of role names are valid. 3290Sstevel@tonic-gate * 3300Sstevel@tonic-gate * Returns NULL if all role names are valid. 3310Sstevel@tonic-gate * Otherwise, returns the invalid role name 3320Sstevel@tonic-gate * 3330Sstevel@tonic-gate */ 3340Sstevel@tonic-gate static const char * 3350Sstevel@tonic-gate check_role(const char *roles) 3360Sstevel@tonic-gate { 3370Sstevel@tonic-gate char *rolename; 3380Sstevel@tonic-gate userattr_t *result; 3390Sstevel@tonic-gate char *utype; 3400Sstevel@tonic-gate char *tmp; 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate tmp = strdup(roles); 34312578SGlenn.Faden@Sun.COM if (tmp == NULL) { 34412578SGlenn.Faden@Sun.COM errmsg(M_NOSPACE); 34512578SGlenn.Faden@Sun.COM exit(EX_FAILURE); 34612578SGlenn.Faden@Sun.COM } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate rolename = strtok(tmp, ROLE_SEP); 3490Sstevel@tonic-gate while (rolename != NULL) { 3500Sstevel@tonic-gate result = getusernam(rolename); 3510Sstevel@tonic-gate if (result == NULL) { 3520Sstevel@tonic-gate /* can't find the rolename */ 3530Sstevel@tonic-gate return (rolename); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate /* Now, make sure it is a role */ 3560Sstevel@tonic-gate utype = kva_match(result->attr, USERATTR_TYPE_KW); 3570Sstevel@tonic-gate if (utype == NULL) { 3580Sstevel@tonic-gate /* no user type defined. not a role */ 3590Sstevel@tonic-gate free_userattr(result); 3600Sstevel@tonic-gate return (rolename); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate if (strcmp(utype, USERATTR_TYPE_NONADMIN_KW) != 0) { 3630Sstevel@tonic-gate free_userattr(result); 3640Sstevel@tonic-gate return (rolename); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate free_userattr(result); 3670Sstevel@tonic-gate rolename = strtok(NULL, ROLE_SEP); 3680Sstevel@tonic-gate } 36912578SGlenn.Faden@Sun.COM free(tmp); 3700Sstevel@tonic-gate return (NULL); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate static const char * 3740Sstevel@tonic-gate check_proj(const char *proj) 3750Sstevel@tonic-gate { 3760Sstevel@tonic-gate if (getprojidbyname(proj) < 0) { 3770Sstevel@tonic-gate return (proj); 3780Sstevel@tonic-gate } else { 3790Sstevel@tonic-gate return (NULL); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate static const char * 3840Sstevel@tonic-gate check_privset(const char *pset) 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate priv_set_t *tmp; 3870Sstevel@tonic-gate const char *res; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate tmp = priv_str_to_set(pset, ",", &res); 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate if (tmp != NULL) { 3920Sstevel@tonic-gate res = NULL; 3930Sstevel@tonic-gate priv_freeset(tmp); 3940Sstevel@tonic-gate } else if (res == NULL) 3950Sstevel@tonic-gate res = strerror(errno); 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate return (res); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate static const char * 4010Sstevel@tonic-gate check_type(const char *type) 4020Sstevel@tonic-gate { 4030Sstevel@tonic-gate if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) != 0 && 4040Sstevel@tonic-gate strcmp(type, USERATTR_TYPE_NORMAL_KW) != 0) 4050Sstevel@tonic-gate return (type); 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate return (NULL); 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate static const char * 4110Sstevel@tonic-gate check_lock_after_retries(const char *keyval) 4120Sstevel@tonic-gate { 4130Sstevel@tonic-gate if (keyval != NULL) { 4140Sstevel@tonic-gate if ((strcasecmp(keyval, "no") != 0) && 4150Sstevel@tonic-gate (strcasecmp(keyval, "yes") != 0) && 4160Sstevel@tonic-gate (*keyval != '\0')) { 4170Sstevel@tonic-gate return (keyval); 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate return (NULL); 4210Sstevel@tonic-gate } 4222657Srica 4232657Srica static const char * 4242657Srica check_label(const char *labelstr) 4252657Srica { 4262657Srica int err; 4272657Srica m_label_t *lbl = NULL; 4282657Srica 4292657Srica if (!is_system_labeled()) 4302657Srica return (NULL); 4312657Srica 4322657Srica err = str_to_label(labelstr, &lbl, MAC_LABEL, L_NO_CORRECTION, NULL); 4332657Srica m_label_free(lbl); 4342657Srica 4352657Srica if (err == -1) 4362657Srica return (labelstr); 4372657Srica 4382657Srica return (NULL); 4392657Srica } 4402657Srica 4412657Srica static const char * 4422657Srica check_idlecmd(const char *cmd) 4432657Srica { 4442657Srica if ((strcmp(cmd, USERATTR_IDLECMD_LOCK_KW) != 0) && 4452657Srica (strcmp(cmd, USERATTR_IDLECMD_LOGOUT_KW) != 0)) { 4462657Srica return (cmd); 4472657Srica } 4482657Srica 4492657Srica return (NULL); 4502657Srica } 4512657Srica 4522657Srica static const char * 4532657Srica check_idletime(const char *time) 4542657Srica { 4552657Srica int c; 4562657Srica unsigned char *up = (unsigned char *)time; 4572657Srica 4582657Srica c = *up; 4592657Srica while (c != '\0') { 4602657Srica if (!isdigit(c)) 4612657Srica return (time); 4622657Srica c = *++up; 4632657Srica } 4642657Srica 4652657Srica return (NULL); 4662657Srica } 467