Index: usr.bin/cap_mkdb/Makefile =================================================================== --- usr.bin/cap_mkdb/Makefile +++ usr.bin/cap_mkdb/Makefile @@ -1,6 +1,11 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= cap_mkdb + +LIBADD= ucl +LIBADD= sbuf .include Index: usr.bin/cap_mkdb/cap_mkdb.c =================================================================== --- usr.bin/cap_mkdb/cap_mkdb.c +++ usr.bin/cap_mkdb/cap_mkdb.c @@ -50,11 +50,14 @@ #include #include #include +#include #include #include #include +#include #include +static void db_ucl(char **, int); static void db_build(char **); static void dounlink(void); static void usage(void); @@ -82,7 +85,9 @@ int main(int argc, char *argv[]) { - int byteorder, c; + int byteorder, c, uclver, n; + char line[BUFSIZ]; + FILE *cf; capname = NULL; byteorder = 0; @@ -128,8 +133,27 @@ if (atexit(dounlink)) err(1, "atexit"); - db_build(argv); + cf = fopen(argv[0], "r"); + if (!cf || fgets(line, BUFSIZ, cf) == NULL) { + errx(1, "Failed to read config file\n"); + } + fclose(cf); + if (strncmp(line, "#fucl", 5) == 0) { + /* The config file is a FreeBSD UCL */ + /* Determine its schema version */ + if (strlen(line) < 7) + errx(1, "Error: Invalid UCL header: %s\n", line); + n = sscanf(line + 5, "%i", &uclver); + if (n == 0 || uclver == 0) + errx(1, "Error: UCL version number is invalid: '%s'\n", line + 5); + if (uclver > 1) + errx(1, "UCL version too new\n"); + else if (uclver == 1) + db_ucl(argv, argc); + } else + db_build(argv); + if (capdbp->close(capdbp) < 0) err(1, "%s", capname); capname = NULL; @@ -161,7 +185,7 @@ DBT key, data; recno_t reccnt; size_t len, bplen; - int st; + int st, i; char *bp, *p, *t; data.data = NULL; @@ -205,7 +229,7 @@ key.data = bp; key.size = p - bp; - switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) { + switch(i = capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) { case -1: err(1, "put"); /* NOTREACHED */ @@ -259,6 +283,128 @@ if (verbose) (void)printf("cap_mkdb: %d capability records\n", reccnt); +} + +/* + * db_ucl() builds the name and capability databases according from a + * Universal Config Language file. + * + * Returns 0 on success, 1 on error + */ +static void +db_ucl(char **ifiles, int filecount) +{ + DBT key, data; + recno_t reccnt; + size_t len; + int i; + //char *a1, *a2; + char *tok, *class_key, *cap_data, *keys, *tofree; + struct ucl_parser *parser = NULL; + ucl_object_t *conf_root = NULL; + ucl_object_iter_t it_class = NULL, it_cap = NULL; + const ucl_object_t *obj_class = NULL, *obj_cap = NULL; + struct sbuf *sb_data; + + reccnt = 0; + + parser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE); + + for (i = 0; i < filecount; i++) { + ucl_parser_add_file(parser, ifiles[i]); + if (ucl_parser_get_error(parser)) { + errx(1, "UCL Error occured: %s\n", + ucl_parser_get_error(parser)); + } + } + + conf_root = ucl_parser_get_object(parser); + if (ucl_parser_get_error(parser)) { + errx(1, "Error: Parse Error occured: %s\n", + ucl_parser_get_error(parser)); + } + + it_class = ucl_object_iterate_new(conf_root); + while ((obj_class = ucl_object_iterate_safe(it_class, true)) != NULL) { + data.data = NULL; + key.data = NULL; + class_key = strdup(ucl_object_key(obj_class)); + it_cap = ucl_object_iterate_new(obj_class); + sb_data = sbuf_new_auto(); + /* Leave the first byte available for the record indicator */ + sbuf_cat(sb_data, " "); + /* Add the key name */ + sbuf_printf(sb_data, "%s:\n", class_key); + while ((obj_cap = ucl_object_iterate_safe(it_cap, true)) != NULL) { + sbuf_printf(sb_data, ":%s=%s:\n", ucl_object_key(obj_cap), ucl_object_tostring_forced(obj_cap)); + } + + if (sbuf_finish(sb_data) != 0) + err(1, "Could not allocate memory"); + + cap_data = sbuf_data(sb_data); + len = sbuf_len(sb_data) + 1; + data.data = realloc(data.data, len); + memmove(data.data, cap_data, len); + //snprintf(data.data, len, "%s", cap_data); + data.size = len; + /* First byte of stored record indicates status. */ + ((char *)(data.data))[0] = RECOK; + /* Store the record under the name field. */ + len = strlen(class_key) + 1; + key.data = realloc(key.data, len); + memmove(key.data, class_key, len); + key.size = len; + + sbuf_delete(sb_data); + + switch(i = capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) { + case -1: + err(1, "put"); + /* NOTREACHED */ + case 1: + warnx("ignored duplicate: %.*s", + (int)key.size, (char *)key.data); + continue; + } + ++reccnt; + + /* If only one name, ignore the rest. */ + if (strchr(class_key, '|') == NULL) + continue; + + /* The rest of the names reference the entire name. */ + ((char *)(data.data))[0] = SHADOW; + memmove(&((u_char *)(data.data))[1], key.data, key.size); + data.size = key.size + 1; + + /* Store references for other names. */ + tofree = keys = strdup(class_key); + if (keys == NULL) { + errx(1, "malloc failed"); + } + + while ((tok = strsep(&keys, "|")) != NULL) { + key.data = strdup(tok); + key.size = strlen(key.data) + 1; + + switch(capdbp->put(capdbp, + &key, &data, R_NOOVERWRITE)) { + case -1: + err(1, "put"); + /* NOTREACHED */ + case 1: + warnx("ignored duplicate: %.*s", + (int)key.size, (char *)key.data); + } + } + + free(tofree); + } + + if (verbose) + (void)printf("cap_mkdb: %d capability records\n", reccnt); + } static void Index: usr.bin/login/login.conf =================================================================== --- usr.bin/login/login.conf +++ usr.bin/login/login.conf @@ -1,3 +1,4 @@ +#fucl1 # login.conf - login class capabilities database. # # Remember to rebuild the database after each change to this file: @@ -22,79 +23,83 @@ # value or name of a capability (see the ``CGETNUM AND CGETSTR SYNTAX # AND SEMANTICS'' section of getcap(3) for more escape sequences). -default:\ - :passwd_format=sha512:\ - :copyright=/etc/COPYRIGHT:\ - :welcome=/var/run/motd:\ - :setenv=BLOCKSIZE=K:\ - :mail=/var/mail/$:\ - :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:\ - :nologin=/var/run/nologin:\ - :cputime=unlimited:\ - :datasize=unlimited:\ - :stacksize=unlimited:\ - :memorylocked=64K:\ - :memoryuse=unlimited:\ - :filesize=unlimited:\ - :coredumpsize=unlimited:\ - :openfiles=unlimited:\ - :maxproc=unlimited:\ - :sbsize=unlimited:\ - :vmemoryuse=unlimited:\ - :swapuse=unlimited:\ - :pseudoterminals=unlimited:\ - :kqueues=unlimited:\ - :umtxp=unlimited:\ - :priority=0:\ - :ignoretime@:\ - :umask=022: +default { + passwd_format=sha512 + copyright=/etc/COPYRIGHT + welcome=/var/run/motd + setenv=BLOCKSIZE=K + path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin + nologin=/var/run/nologin + cputime=unlimited + datasize=unlimited + stacksize=unlimited + memorylocked=64KB + memoryuse=unlimited + filesize=unlimited + coredumpsize=unlimited + openfiles=unlimited + maxproc=unlimited + sbsize=unlimited + vmemoryuse=unlimited + swapuse=unlimited + pseudoterminals=unlimited + kqueues=unlimited + umtxp=unlimited + priority=0 + ignoretime=true + umask=022 +} - # # A collection of common class names - forward them all to 'default' # (login would normally do this anyway, but having a class name # here suppresses the diagnostic) # -standard:\ - :tc=default: -xuser:\ - :tc=default: -staff:\ - :tc=default: +standard { + .inherit "default" +} -# This PATH may be clobbered by individual applications. Notably, by default, -# rc(8), service(8), and cron(8) will all override it with a default PATH that -# may not include /usr/local/sbin and /usr/local/bin when starting services or -# jobs. -daemon:\ - :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin:\ - :mail@:\ - :memorylocked=128M:\ - :tc=default: -news:\ - :tc=default: -dialer:\ - :tc=default: +xuser { + .inherit "default" +} +staff { + .inherit "default" +} + +daemon { + .inherit "default" + memorylocked=128MB +} + +news { + .inherit "default" +} + +dialer { + .inherit "default" +} + # # Root can always login # # N.B. login_getpwclass(3) will use this entry for the root account, # in preference to 'default'. -root:\ - :ignorenologin:\ - :memorylocked=unlimited:\ - :tc=default: +root { + ignorenologin + memorylocked=unlimited + .inherit "default" +} # # Russian Users Accounts. Setup proper environment variables. # -russian|Russian Users Accounts:\ - :charset=UTF-8:\ - :lang=ru_RU.UTF-8:\ - :tc=default: +"russian|Russian Users Accounts" { + charset=UTF-8 + lang=ru_RU.UTF-8 + .inherit "default" +} - ###################################################################### ###################################################################### ## @@ -107,225 +112,225 @@ ## These settings are used by login(1) by default for classless users ## Note that entries like "cputime" set both "cputime-cur" and "cputime-max" # -#default:\ -# :cputime=infinity:\ -# :datasize-cur=22M:\ -# :stacksize-cur=8M:\ -# :memorylocked-cur=10M:\ -# :memoryuse-cur=30M:\ -# :filesize=infinity:\ -# :coredumpsize=infinity:\ -# :maxproc-cur=64:\ -# :openfiles-cur=64:\ -# :priority=0:\ -# :requirehome@:\ -# :umask=022:\ -# :tc=auth-defaults: +#default { +# cputime=infinity +# datasize-cur=22M +# stacksize-cur=8M +# memorylocked-cur=10M +# memoryuse-cur=30M +# filesize=infinity +# coredumpsize=infinity +# maxproc-cur=64 +# openfiles-cur=64 +# priority=0 +# requirehome=true +# umask=022 +# .inherit auth-defaults +#} # -# ## ## standard - standard user defaults ## -#standard:\ -# :copyright=/etc/COPYRIGHT:\ -# :welcome=/var/run/motd:\ -# :setenv=BLOCKSIZE=K:\ -# :mail=/var/mail/$:\ -# :path=~/bin /bin /usr/bin /usr/local/bin:\ -# :manpath=/usr/share/man /usr/local/man:\ -# :nologin=/var/run/nologin:\ -# :cputime=1h30m:\ -# :datasize=8M:\ -# :vmemoryuse=100M:\ -# :stacksize=2M:\ -# :memorylocked=4M:\ -# :memoryuse=8M:\ -# :filesize=8M:\ -# :coredumpsize=8M:\ -# :openfiles=24:\ -# :maxproc=32:\ -# :priority=0:\ -# :requirehome:\ -# :passwordtime=90d:\ -# :umask=002:\ -# :ignoretime@:\ -# :tc=default: +#standard { +# copyright=/etc/COPYRIGHT +# welcome=/etc/motd +# setenv=MAIL=/var/mail/$,BLOCKSIZE=K +# path=~/bin /bin /usr/bin /usr/local/bin +# manpath=/usr/share/man /usr/local/man +# nologin=/var/run/nologin +# cputime=1h30m +# datasize=8M +# vmemoryuse=100M +# stacksize=2M +# memorylocked=4M +# memoryuse=8M +# filesize=8M +# coredumpsize=8M +# openfiles=24 +# maxproc=32 +# priority=0 +# requirehome +# passwordtime=90d +# umask=002 +# ignoretime=true +# .inherit "default" +#} # -# ## ## users of X (needs more resources!) ## -#xuser:\ -# :manpath=/usr/share/man /usr/local/man:\ -# :cputime=4h:\ -# :datasize=12M:\ -# :vmemoryuse=infinity:\ -# :stacksize=4M:\ -# :filesize=8M:\ -# :memoryuse=16M:\ -# :openfiles=32:\ -# :maxproc=48:\ -# :tc=standard: +#xuser { +# manpath=/usr/share/man /usr/local/man +# cputime=4h +# datasize=12M +# vmemoryuse=infinity +# stacksize=4M +# filesize=8M +# memoryuse=16M +# openfiles=32 +# maxproc=48 +# .inherit standard +#} # -# ## ## Staff users - few restrictions and allow login anytime ## -#staff:\ -# :ignorenologin:\ -# :ignoretime:\ -# :requirehome@:\ -# :accounted@:\ -# :path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\ -# :umask=022:\ -# :tc=standard: +#staff { +# ignorenologin +# ignoretime +# requirehome=true +# accounted=true +# path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin +# umask=022 +# .inherit standard +#} # -# ## ## root - fallback for root logins ## -#root:\ -# :path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\ -# :cputime=infinity:\ -# :datasize=infinity:\ -# :stacksize=infinity:\ -# :memorylocked=infinity:\ -# :memoryuse=infinity:\ -# :filesize=infinity:\ -# :coredumpsize=infinity:\ -# :openfiles=infinity:\ -# :maxproc=infinity:\ -# :memoryuse-cur=32M:\ -# :maxproc-cur=64:\ -# :openfiles-cur=1024:\ -# :priority=0:\ -# :requirehome@:\ -# :umask=022:\ -# :tc=auth-root-defaults: +#root { +# path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin +# cputime=infinity +# datasize=infinity +# stacksize=infinity +# memorylocked=infinity +# memoryuse=infinity +# filesize=infinity +# coredumpsize=infinity +# openfiles=infinity +# maxproc=infinity +# memoryuse-cur=32M +# maxproc-cur=64 +# openfiles-cur=1024 +# priority=0 +# requirehome=true +# umask=022 +# .inherit auth-root-defaults +#} # -# ## ## Settings used by /etc/rc ## -#daemon:\ -# :coredumpsize@:\ -# :coredumpsize-cur=0:\ -# :datasize=infinity:\ -# :datasize-cur@:\ -# :maxproc=512:\ -# :maxproc-cur@:\ -# :memoryuse-cur=64M:\ -# :memorylocked-cur=64M:\ -# :openfiles=1024:\ -# :openfiles-cur@:\ -# :stacksize=16M:\ -# :stacksize-cur@:\ -# :tc=default: +#daemon { +# .inherit "default" +# coredumpsize +# coredumpsize-cur +# datasize=infinity +# datasize-cur +# maxproc=512 +# maxproc-cur +# memoryuse-cur=64M +# memorylocked-cur=64M +# openfiles=1024 +# openfiles-cur +# stacksize=16M +# stacksize-cur +#} # -# ## ## Settings used by news subsystem ## -#news:\ -# :path=/usr/local/news/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\ -# :cputime=infinity:\ -# :filesize=128M:\ -# :datasize-cur=64M:\ -# :stacksize-cur=32M:\ -# :coredumpsize-cur=0:\ -# :maxmemorysize-cur=128M:\ -# :memorylocked=32M:\ -# :maxproc=128:\ -# :openfiles=256:\ -# :tc=default: +#news { +# .inherit "default" +# path=/usr/local/news/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin +# cputime=infinity +# filesize=128M +# datasize-cur=64M +# stacksize-cur=32M +# coredumpsize-cur=0 +# maxmemorysize-cur=128M +# memorylocked=32M +# maxproc=128 +# openfiles=256 +#} # -# ## ## The dialer class should be used for a dialup PPP account ## Welcome messages/news suppressed ## -#dialer:\ -# :hushlogin:\ -# :requirehome@:\ -# :cputime=unlimited:\ -# :filesize=2M:\ -# :datasize=2M:\ -# :stacksize=4M:\ -# :coredumpsize=0:\ -# :memoryuse=4M:\ -# :memorylocked=1M:\ -# :maxproc=16:\ -# :openfiles=32:\ -# :tc=standard: +#dialer { +# .inherit "standard" +# hushlogin +# requirehome@ +# cputime=unlimited +# filesize=2M +# datasize=2M +# stacksize=4M +# coredumpsize=0 +# memoryuse=4M +# memorylocked=1M +# maxproc=16 +# openfiles=32 +#} # -# ## ## Site full-time 24/7 PPP connection ## - no time accounting, restricted to access via dialin lines ## -#site:\ -# :ignoretime:\ -# :passwordtime@:\ -# :refreshtime@:\ -# :refreshperiod@:\ -# :sessionlimit@:\ -# :autodelete@:\ -# :expireperiod@:\ -# :graceexpire@:\ -# :gracetime@:\ -# :warnexpire@:\ -# :warnpassword@:\ -# :idletime@:\ -# :sessiontime@:\ -# :daytime@:\ -# :weektime@:\ -# :monthtime@:\ -# :warntime@:\ -# :accounted@:\ -# :tc=dialer:\ -# :tc=staff: +#site { +# ignoretime +# passwordtime@ +# refreshtime@ +# refreshperiod@ +# sessionlimit@ +# autodelete@ +# expireperiod@ +# graceexpire@ +# gracetime@ +# warnexpire@ +# warnpassword@ +# idletime@ +# sessiontime@ +# daytime@ +# weektime@ +# monthtime@ +# warntime@ +# accounted@ +# .inherit dialer +# .inherit staff +#} # -# ## ## Example standard accounting entries for subscriber levels ## # -#subscriber|Subscribers:\ -# :accounted:\ -# :refreshtime=180d:\ -# :refreshperiod@:\ -# :sessionlimit@:\ -# :autodelete=30d:\ -# :expireperiod=180d:\ -# :graceexpire=7d:\ -# :gracetime=10m:\ -# :warnexpire=7d:\ -# :warnpassword=7d:\ -# :idletime=30m:\ -# :sessiontime=4h:\ -# :daytime=6h:\ -# :weektime=40h:\ -# :monthtime=120h:\ -# :warntime=4h:\ -# :tc=standard: +#subscriber|Subscribers { +# accounted +# refreshtime=180d +# refreshperiod@ +# sessionlimit@ +# autodelete=30d +# expireperiod=180d +# graceexpire=7d +# gracetime=10m +# warnexpire=7d +# warnpassword=7d +# idletime=30m +# sessiontime=4h +# daytime=6h +# weektime=40h +# monthtime=120h +# warntime=4h +# .inherit standard +#} # -# ## ## Subscriber accounts. These accounts have their login times ## accounted and have access limits applied. ## -#subppp|PPP Subscriber Accounts:\ -# :tc=dialer:\ -# :tc=subscriber: +#subppp|PPP Subscriber Accounts { +# .inherit dialer +# .inherit subscriber +#} # -# -#subshell|Shell Subscriber Accounts:\ -# :tc=subscriber: -# +#subshell|Shell Subscriber Accounts { +# .inherit subscriber +#} ## ## If you want some of the accounts to use traditional UNIX DES based ## password hashes. ## -#des_users:\ -# :passwd_format=des:\ -# :tc=default: +#des_users { +# passwd_format=des +# .inherit "default" +#}