From 50568f27d680f3a286fdcfaebb5e4f361c4c7e8b Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 10 Mar 2010 02:16:04 +0000 Subject: Create the altix project branch. The altix project will add support for the SGI Altix 350 to FreeBSD/ia64. The hardware used for porting is a two-module system, consisting of a base compute module and a CPU expansion module. SGI's NUMAFlex architecture can be an excellent platform to test CPU affinity and NUMA-aware features in FreeBSD. --- libutil/_secure_path.c | 74 ----- libutil/flopen.c | 105 ------- libutil/gr_util.c | 250 --------------- libutil/libutil.h | 212 ------------- libutil/login_cap.c | 819 ------------------------------------------------- libutil/login_cap.h | 166 ---------- libutil/login_crypt.c | 50 --- libutil/pw_util.c | 621 ------------------------------------- 8 files changed, 2297 deletions(-) delete mode 100644 libutil/_secure_path.c delete mode 100644 libutil/flopen.c delete mode 100644 libutil/gr_util.c delete mode 100644 libutil/libutil.h delete mode 100644 libutil/login_cap.c delete mode 100644 libutil/login_cap.h delete mode 100644 libutil/login_crypt.c delete mode 100644 libutil/pw_util.c (limited to 'libutil') diff --git a/libutil/_secure_path.c b/libutil/_secure_path.c deleted file mode 100644 index 363378b..0000000 --- a/libutil/_secure_path.c +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * Based on code copyright (c) 1995,1997 by - * Berkeley Software Design, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. This work was done expressly for inclusion into FreeBSD. Other use - * is permitted provided this notation is included. - * 4. Absolutely no warranty of function or purpose is made by the authors. - * 5. Modifications may be freely made to this file providing the above - * conditions are met. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include -#include - -/* - * Check for common security problems on a given path - * It must be: - * 1. A regular file, and exists - * 2. Owned and writable only by root (or given owner) - * 3. Group ownership is given group or is non-group writable - * - * Returns: -2 if file does not exist, - * -1 if security test failure - * 0 otherwise - */ - -int -_secure_path(const char *path, uid_t uid, gid_t gid) -{ - int r = -1; - struct stat sb; - const char *msg = NULL; - - if (lstat(path, &sb) < 0) { - if (errno == ENOENT) /* special case */ - r = -2; /* if it is just missing, skip the log entry */ - else - msg = "%s: cannot stat %s: %m"; - } - else if (!S_ISREG(sb.st_mode)) - msg = "%s: %s is not a regular file"; - else if (sb.st_mode & S_IWOTH) - msg = "%s: %s is world writable"; - else if ((int)uid != -1 && sb.st_uid != uid && sb.st_uid != 0) { - if (uid == 0) - msg = "%s: %s is not owned by root"; - else - msg = "%s: %s is not owned by uid %d"; - } else if ((int)gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP)) - msg = "%s: %s is group writeable by non-authorised groups"; - else - r = 0; - if (msg != NULL) - syslog(LOG_ERR, msg, "_secure_path", path, uid); - return r; -} diff --git a/libutil/flopen.c b/libutil/flopen.c deleted file mode 100644 index 754c9c0..0000000 --- a/libutil/flopen.c +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include - -#include - -int -flopen(const char *path, int flags, ...) -{ - int fd, operation, serrno, trunc; - struct stat sb, fsb; - mode_t mode; - -#ifdef O_EXLOCK - flags &= ~O_EXLOCK; -#endif - - mode = 0; - if (flags & O_CREAT) { - va_list ap; - - va_start(ap, flags); - mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ - va_end(ap); - } - - operation = LOCK_EX; - if (flags & O_NONBLOCK) - operation |= LOCK_NB; - - trunc = (flags & O_TRUNC); - flags &= ~O_TRUNC; - - for (;;) { - if ((fd = open(path, flags, mode)) == -1) - /* non-existent or no access */ - return (-1); - if (flock(fd, operation) == -1) { - /* unsupported or interrupted */ - serrno = errno; - (void)close(fd); - errno = serrno; - return (-1); - } - if (stat(path, &sb) == -1) { - /* disappeared from under our feet */ - (void)close(fd); - continue; - } - if (fstat(fd, &fsb) == -1) { - /* can't happen [tm] */ - serrno = errno; - (void)close(fd); - errno = serrno; - return (-1); - } - if (sb.st_dev != fsb.st_dev || - sb.st_ino != fsb.st_ino) { - /* changed under our feet */ - (void)close(fd); - continue; - } - if (trunc && ftruncate(fd, 0) != 0) { - /* can't happen [tm] */ - serrno = errno; - (void)close(fd); - errno = serrno; - return (-1); - } - return (fd); - } -} diff --git a/libutil/gr_util.c b/libutil/gr_util.c deleted file mode 100644 index 633f435..0000000 --- a/libutil/gr_util.c +++ /dev/null @@ -1,250 +0,0 @@ -/*- - * Copyright (c) 2008 Sean C. Farley - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include -#include -#include - -struct group_storage { - struct group gr; - char *members[]; -}; - -static const char group_line_format[] = "%s:%s:%ju:"; - -/* - * Compares two struct group's. - */ -int -gr_equal(const struct group *gr1, const struct group *gr2) -{ - int gr1_ndx; - int gr2_ndx; - bool found; - - /* Check that the non-member information is the same. */ - if (gr1->gr_name == NULL || gr2->gr_name == NULL) { - if (gr1->gr_name != gr2->gr_name) - return (false); - } else if (strcmp(gr1->gr_name, gr2->gr_name) != 0) - return (false); - if (gr1->gr_passwd == NULL || gr2->gr_passwd == NULL) { - if (gr1->gr_passwd != gr2->gr_passwd) - return (false); - } else if (strcmp(gr1->gr_passwd, gr2->gr_passwd) != 0) - return (false); - if (gr1->gr_gid != gr2->gr_gid) - return (false); - - /* Check all members in both groups. */ - if (gr1->gr_mem == NULL || gr2->gr_mem == NULL) { - if (gr1->gr_mem != gr2->gr_mem) - return (false); - } else { - for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; - gr1_ndx++) { - for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL; - gr2_ndx++) - if (strcmp(gr1->gr_mem[gr1_ndx], - gr2->gr_mem[gr2_ndx]) == 0) { - found = true; - break; - } - if (!found) - return (false); - } - - /* Check that group2 does not have more members than group1. */ - if (gr2->gr_mem[gr1_ndx] != NULL) - return (false); - } - - return (true); -} - -/* - * Make a group line out of a struct group. - */ -char * -gr_make(const struct group *gr) -{ - char *line; - size_t line_size; - int ndx; - - /* Calculate the length of the group line. */ - line_size = snprintf(NULL, 0, group_line_format, gr->gr_name, - gr->gr_passwd, (uintmax_t)gr->gr_gid) + 1; - if (gr->gr_mem != NULL) { - for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) - line_size += strlen(gr->gr_mem[ndx]) + 1; - if (ndx > 0) - line_size--; - } - - /* Create the group line and fill it. */ - if ((line = malloc(line_size)) == NULL) - return (NULL); - snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd, - (uintmax_t)gr->gr_gid); - if (gr->gr_mem != NULL) - for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { - strcat(line, gr->gr_mem[ndx]); - if (gr->gr_mem[ndx + 1] != NULL) - strcat(line, ","); - } - - return (line); -} - -/* - * Duplicate a struct group. - */ -struct group * -gr_dup(const struct group *gr) -{ - char *dst; - size_t len; - struct group_storage *gs; - int ndx; - int num_mem; - - /* Calculate size of the group. */ - len = sizeof(*gs); - if (gr->gr_name != NULL) - len += strlen(gr->gr_name) + 1; - if (gr->gr_passwd != NULL) - len += strlen(gr->gr_passwd) + 1; - if (gr->gr_mem != NULL) { - for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++) - len += strlen(gr->gr_mem[num_mem]) + 1; - len += (num_mem + 1) * sizeof(*gr->gr_mem); - } else - num_mem = -1; - - /* Create new group and copy old group into it. */ - if ((gs = calloc(1, len)) == NULL) - return (NULL); - dst = (char *)&gs->members[num_mem + 1]; - if (gr->gr_name != NULL) { - gs->gr.gr_name = dst; - dst = stpcpy(gs->gr.gr_name, gr->gr_name) + 1; - } - if (gr->gr_passwd != NULL) { - gs->gr.gr_passwd = dst; - dst = stpcpy(gs->gr.gr_passwd, gr->gr_passwd) + 1; - } - gs->gr.gr_gid = gr->gr_gid; - if (gr->gr_mem != NULL) { - gs->gr.gr_mem = gs->members; - for (ndx = 0; ndx < num_mem; ndx++) { - gs->gr.gr_mem[ndx] = dst; - dst = stpcpy(gs->gr.gr_mem[ndx], gr->gr_mem[ndx]) + 1; - } - gs->gr.gr_mem[ndx] = NULL; - } - - return (&gs->gr); -} - -/* - * Scan a line and place it into a group structure. - */ -static bool -__gr_scan(char *line, struct group *gr) -{ - char *loc; - int ndx; - - /* Assign non-member information to structure. */ - gr->gr_name = line; - if ((loc = strchr(line, ':')) == NULL) - return (false); - *loc = '\0'; - gr->gr_passwd = loc + 1; - if (*gr->gr_passwd == ':') - *gr->gr_passwd = '\0'; - else { - if ((loc = strchr(loc + 1, ':')) == NULL) - return (false); - *loc = '\0'; - } - if (sscanf(loc + 1, "%u", &gr->gr_gid) != 1) - return (false); - - /* Assign member information to structure. */ - if ((loc = strchr(loc + 1, ':')) == NULL) - return (false); - line = loc + 1; - gr->gr_mem = NULL; - ndx = 0; - do { - gr->gr_mem = reallocf(gr->gr_mem, sizeof(*gr->gr_mem) * - (ndx + 1)); - if (gr->gr_mem == NULL) - return (false); - - /* Skip locations without members (i.e., empty string). */ - do { - gr->gr_mem[ndx] = strsep(&line, ","); - } while (gr->gr_mem[ndx] != NULL && *gr->gr_mem[ndx] == '\0'); - } while (gr->gr_mem[ndx++] != NULL); - - return (true); -} - -/* - * Create a struct group from a line. - */ -struct group * -gr_scan(const char *line) -{ - struct group gr; - char *line_copy; - struct group *new_gr; - - if ((line_copy = strdup(line)) == NULL) - return (NULL); - if (!__gr_scan(line_copy, &gr)) { - free(line_copy); - return (NULL); - } - new_gr = gr_dup(&gr); - free(line_copy); - if (gr.gr_mem != NULL) - free(gr.gr_mem); - - return (new_gr); -} diff --git a/libutil/libutil.h b/libutil/libutil.h deleted file mode 100644 index 4c2ee3b..0000000 --- a/libutil/libutil.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 1996 Peter Wemm . - * All rights reserved. - * Copyright (c) 2002 Networks Associates Technology, Inc. - * All rights reserved. - * - * Portions of this software were developed for the FreeBSD Project by - * ThinkSec AS and NAI Labs, the Security Research Division of Network - * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 - * ("CBOSS"), as part of the DARPA CHATS research program. - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _LIBUTIL_H_ -#define _LIBUTIL_H_ - -#include -#include - -#ifndef _GID_T_DECLARED -typedef __gid_t gid_t; -#define _GID_T_DECLARED -#endif - -#ifndef _INT64_T_DECLARED -typedef __int64_t int64_t; -#define _INT64_T_DECLARED -#endif - -#ifndef _PID_T_DECLARED -typedef __pid_t pid_t; -#define _PID_T_DECLARED -#endif - -#ifndef _SIZE_T_DECLARED -typedef __size_t size_t; -#define _SIZE_T_DECLARED -#endif - -#ifndef _UID_T_DECLARED -typedef __uid_t uid_t; -#define _UID_T_DECLARED -#endif - -#define PROPERTY_MAX_NAME 64 -#define PROPERTY_MAX_VALUE 512 - -/* for properties.c */ -typedef struct _property { - struct _property *next; - char *name; - char *value; -} *properties; - -#ifdef _SYS_PARAM_H_ -/* for pidfile.c */ -struct pidfh { - int pf_fd; - char pf_path[MAXPATHLEN + 1]; - __dev_t pf_dev; - ino_t pf_ino; -}; -#endif - -/* Avoid pulling in all the include files for no need */ -struct termios; -struct winsize; -struct in_addr; -struct kinfo_file; -struct kinfo_vmentry; - -__BEGIN_DECLS -void clean_environment(const char * const *_white, - const char * const *_more_white); -int extattr_namespace_to_string(int _attrnamespace, char **_string); -int extattr_string_to_namespace(const char *_string, int *_attrnamespace); -int flopen(const char *_path, int _flags, ...); -void hexdump(const void *ptr, int length, const char *hdr, int flags); -int login_tty(int _fd); -void trimdomain(char *_fullhost, int _hostsize); -int openpty(int *_amaster, int *_aslave, char *_name, - struct termios *_termp, struct winsize *_winp); -int forkpty(int *_amaster, char *_name, - struct termios *_termp, struct winsize *_winp); -int humanize_number(char *_buf, size_t _len, int64_t _number, - const char *_suffix, int _scale, int _flags); -int expand_number(const char *_buf, int64_t *_num); -const char *uu_lockerr(int _uu_lockresult); -int uu_lock(const char *_ttyname); -int uu_unlock(const char *_ttyname); -int uu_lock_txfr(const char *_ttyname, pid_t _pid); -int _secure_path(const char *_path, uid_t _uid, gid_t _gid); -properties properties_read(int fd); -void properties_free(properties list); -char *property_find(properties list, const char *name); -char *auth_getval(const char *name); -int realhostname(char *host, size_t hsize, const struct in_addr *ip); -struct sockaddr; -int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, - int addrlen); - -int kld_isloaded(const char *name); -int kld_load(const char *name); -struct kinfo_file * - kinfo_getfile(pid_t _pid, int *_cntp); -struct kinfo_vmentry * - kinfo_getvmmap(pid_t _pid, int *_cntp); - -#ifdef _STDIO_H_ /* avoid adding new includes */ -char *fparseln(FILE *, size_t *, size_t *, const char[3], int); -#endif - -#ifdef _PWD_H_ -int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw); -struct passwd *pw_dup(const struct passwd *_pw); -int pw_edit(int _notsetuid); -int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2); -void pw_fini(void); -int pw_init(const char *_dir, const char *_master); -char *pw_make(const struct passwd *_pw); -int pw_mkdb(const char *_user); -int pw_lock(void); -struct passwd *pw_scan(const char *_line, int _flags); -const char *pw_tempname(void); -int pw_tmp(int _mfd); -#endif - -#ifdef _GRP_H_ -int gr_equal(const struct group *gr1, const struct group *gr2); -char *gr_make(const struct group *gr); -struct group *gr_dup(const struct group *gr); -struct group *gr_scan(const char *line); -#endif - -#ifdef _SYS_PARAM_H_ -struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr); -int pidfile_write(struct pidfh *pfh); -int pidfile_close(struct pidfh *pfh); -int pidfile_remove(struct pidfh *pfh); -#endif - -__END_DECLS - -#define UU_LOCK_INUSE (1) -#define UU_LOCK_OK (0) -#define UU_LOCK_OPEN_ERR (-1) -#define UU_LOCK_READ_ERR (-2) -#define UU_LOCK_CREAT_ERR (-3) -#define UU_LOCK_WRITE_ERR (-4) -#define UU_LOCK_LINK_ERR (-5) -#define UU_LOCK_TRY_ERR (-6) -#define UU_LOCK_OWNER_ERR (-7) - -/* return values from realhostname() */ -#define HOSTNAME_FOUND (0) -#define HOSTNAME_INCORRECTNAME (1) -#define HOSTNAME_INVALIDADDR (2) -#define HOSTNAME_INVALIDNAME (3) - -/* fparseln(3) */ -#define FPARSELN_UNESCESC 0x01 -#define FPARSELN_UNESCCONT 0x02 -#define FPARSELN_UNESCCOMM 0x04 -#define FPARSELN_UNESCREST 0x08 -#define FPARSELN_UNESCALL 0x0f - -/* pw_scan() */ -#define PWSCAN_MASTER 0x01 -#define PWSCAN_WARN 0x02 - -/* humanize_number(3) */ -#define HN_DECIMAL 0x01 -#define HN_NOSPACE 0x02 -#define HN_B 0x04 -#define HN_DIVISOR_1000 0x08 - -#define HN_GETSCALE 0x10 -#define HN_AUTOSCALE 0x20 - -/* hexdump(3) */ -#define HD_COLUMN_MASK 0xff -#define HD_DELIM_MASK 0xff00 -#define HD_OMIT_COUNT (1 << 16) -#define HD_OMIT_HEX (1 << 17) -#define HD_OMIT_CHARS (1 << 18) - -#endif /* !_LIBUTIL_H_ */ diff --git a/libutil/login_cap.c b/libutil/login_cap.c deleted file mode 100644 index 8fee760..0000000 --- a/libutil/login_cap.c +++ /dev/null @@ -1,819 +0,0 @@ -/*- - * Copyright (c) 1996 by - * Sean Eric Fagan - * David Nugent - * All rights reserved. - * - * Portions copyright (c) 1995,1997 - * Berkeley Software Design, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. This work was done expressly for inclusion into FreeBSD. Other use - * is permitted provided this notation is included. - * 4. Absolutely no warranty of function or purpose is made by the authors. - * 5. Modifications may be freely made to this file providing the above - * conditions are met. - * - * Low-level routines relating to the user capabilities database - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * allocstr() - * Manage a single static pointer for handling a local char* buffer, - * resizing as necessary to contain the string. - * - * allocarray() - * Manage a static array for handling a group of strings, resizing - * when necessary. - */ - -static int lc_object_count = 0; - -static size_t internal_stringsz = 0; -static char * internal_string = NULL; -static size_t internal_arraysz = 0; -static const char ** internal_array = NULL; - -static char path_login_conf[] = _PATH_LOGIN_CONF; - -static char * -allocstr(const char *str) -{ - char *p; - - size_t sz = strlen(str) + 1; /* realloc() only if necessary */ - if (sz <= internal_stringsz) - p = strcpy(internal_string, str); - else if ((p = realloc(internal_string, sz)) != NULL) { - internal_stringsz = sz; - internal_string = strcpy(p, str); - } - return p; -} - - -static const char ** -allocarray(size_t sz) -{ - static const char **p; - - if (sz <= internal_arraysz) - p = internal_array; - else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) { - internal_arraysz = sz; - internal_array = p; - } - return p; -} - - -/* - * arrayize() - * Turn a simple string separated by any of - * the set of into an array. The last element - * of the array will be NULL, as is proper. - * Free using freearraystr() - */ - -static const char ** -arrayize(const char *str, const char *chars, int *size) -{ - int i; - char *ptr; - const char *cptr; - const char **res = NULL; - - /* count the sub-strings */ - for (i = 0, cptr = str; *cptr; i++) { - int count = strcspn(cptr, chars); - cptr += count; - if (*cptr) - ++cptr; - } - - /* alloc the array */ - if ((ptr = allocstr(str)) != NULL) { - if ((res = allocarray(++i)) == NULL) - free((void *)(uintptr_t)(const void *)str); - else { - /* now split the string */ - i = 0; - while (*ptr) { - int count = strcspn(ptr, chars); - res[i++] = ptr; - ptr += count; - if (*ptr) - *ptr++ = '\0'; - } - res[i] = NULL; - } - } - - if (size) - *size = i; - - return res; -} - - -/* - * login_close() - * Frees up all resources relating to a login class - * - */ - -void -login_close(login_cap_t * lc) -{ - if (lc) { - free(lc->lc_style); - free(lc->lc_class); - free(lc->lc_cap); - free(lc); - if (--lc_object_count == 0) { - free(internal_string); - free(internal_array); - internal_array = NULL; - internal_arraysz = 0; - internal_string = NULL; - internal_stringsz = 0; - cgetclose(); - } - } -} - - -/* - * login_getclassbyname() - * Get the login class by its name. - * If the name given is NULL or empty, the default class - * LOGIN_DEFCLASS (i.e., "default") is fetched. - * If the name given is LOGIN_MECLASS and - * 'pwd' argument is non-NULL and contains an non-NULL - * dir entry, then the file _FILE_LOGIN_CONF is picked - * up from that directory and used before the system - * login database. In that case the system login database - * is looked up using LOGIN_MECLASS, too, which is a bug. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getclassbyname(char const *name, const struct passwd *pwd) -{ - login_cap_t *lc; - - if ((lc = malloc(sizeof(login_cap_t))) != NULL) { - int r, me, i = 0; - uid_t euid = 0; - gid_t egid = 0; - const char *msg = NULL; - const char *dir; - char userpath[MAXPATHLEN]; - - static char *login_dbarray[] = { NULL, NULL, NULL }; - - me = (name != NULL && strcmp(name, LOGIN_MECLASS) == 0); - dir = (!me || pwd == NULL) ? NULL : pwd->pw_dir; - /* - * Switch to user mode before checking/reading its ~/.login_conf - * - some NFSes have root read access disabled. - * - * XXX: This fails to configure additional groups. - */ - if (dir) { - euid = geteuid(); - egid = getegid(); - (void)setegid(pwd->pw_gid); - (void)seteuid(pwd->pw_uid); - } - - if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, - _FILE_LOGIN_CONF) < MAXPATHLEN) { - if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1) - login_dbarray[i++] = userpath; - } - /* - * XXX: Why to add the system database if the class is `me'? - */ - if (_secure_path(path_login_conf, 0, 0) != -1) - login_dbarray[i++] = path_login_conf; - login_dbarray[i] = NULL; - - memset(lc, 0, sizeof(login_cap_t)); - lc->lc_cap = lc->lc_class = lc->lc_style = NULL; - - if (name == NULL || *name == '\0') - name = LOGIN_DEFCLASS; - - switch (cgetent(&lc->lc_cap, login_dbarray, name)) { - case -1: /* Failed, entry does not exist */ - if (me) - break; /* Don't retry default on 'me' */ - if (i == 0) - r = -1; - else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0) - close(r); - /* - * If there's at least one login class database, - * and we aren't searching for a default class - * then complain about a non-existent class. - */ - if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0) - syslog(LOG_ERR, "login_getclass: unknown class '%s'", name); - /* fall-back to default class */ - name = LOGIN_DEFCLASS; - msg = "%s: no default/fallback class '%s'"; - if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0) - break; - /* FALLTHROUGH - just return system defaults */ - case 0: /* success! */ - if ((lc->lc_class = strdup(name)) != NULL) { - if (dir) { - (void)seteuid(euid); - (void)setegid(egid); - } - ++lc_object_count; - return lc; - } - msg = "%s: strdup: %m"; - break; - case -2: - msg = "%s: retrieving class information: %m"; - break; - case -3: - msg = "%s: 'tc=' reference loop '%s'"; - break; - case 1: - msg = "couldn't resolve 'tc=' reference in '%s'"; - break; - default: - msg = "%s: unexpected cgetent() error '%s': %m"; - break; - } - if (dir) { - (void)seteuid(euid); - (void)setegid(egid); - } - if (msg != NULL) - syslog(LOG_ERR, msg, "login_getclass", name); - free(lc); - } - - return NULL; -} - - - -/* - * login_getclass() - * Get the login class for the system (only) login class database. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getclass(const char *cls) -{ - return login_getclassbyname(cls, NULL); -} - - -/* - * login_getpwclass() - * Get the login class for a given password entry from - * the system (only) login class database. - * If the password entry's class field is not set, or - * the class specified does not exist, then use the - * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged - * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getpwclass(const struct passwd *pwd) -{ - const char *cls = NULL; - - if (pwd != NULL) { - cls = pwd->pw_class; - if (cls == NULL || *cls == '\0') - cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; - } - /* - * XXX: pwd should be unused by login_getclassbyname() unless cls is `me', - * so NULL can be passed instead of pwd for more safety. - */ - return login_getclassbyname(cls, pwd); -} - - -/* - * login_getuserclass() - * Get the `me' login class, allowing user overrides via ~/.login_conf. - * Note that user overrides are allowed only in the `me' class. - */ - -login_cap_t * -login_getuserclass(const struct passwd *pwd) -{ - return login_getclassbyname(LOGIN_MECLASS, pwd); -} - - -/* - * login_getcapstr() - * Given a login_cap entry, and a capability name, return the - * value defined for that capability, a default if not found, or - * an error string on error. - */ - -const char * -login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *error) -{ - char *res; - int ret; - - if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') - return def; - - if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - return (ret >= 0) ? res : error; -} - - -/* - * login_getcaplist() - * Given a login_cap entry, and a capability name, return the - * value defined for that capability split into an array of - * strings. - */ - -const char ** -login_getcaplist(login_cap_t *lc, const char *cap, const char *chars) -{ - const char *lstring; - - if (chars == NULL) - chars = ", \t"; - if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL) - return arrayize(lstring, chars, NULL); - return NULL; -} - - -/* - * login_getpath() - * From the login_cap_t , get the capability which is - * formatted as either a space or comma delimited list of paths - * and append them all into a string and separate by semicolons. - * If there is an error of any kind, return . - */ - -const char * -login_getpath(login_cap_t *lc, const char *cap, const char *error) -{ - const char *str; - char *ptr; - int count; - - str = login_getcapstr(lc, cap, NULL, NULL); - if (str == NULL) - return error; - ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */ - while (*ptr) { - count = strcspn(ptr, ", \t"); - ptr += count; - if (*ptr) - *ptr++ = ':'; - } - return str; -} - - -static int -isinfinite(const char *s) -{ - static const char *infs[] = { - "infinity", - "inf", - "unlimited", - "unlimit", - "-1", - NULL - }; - const char **i = &infs[0]; - - while (*i != NULL) { - if (strcasecmp(s, *i) == 0) - return 1; - ++i; - } - return 0; -} - - -static u_quad_t -rmultiply(u_quad_t n1, u_quad_t n2) -{ - u_quad_t m, r; - int b1, b2; - - static int bpw = 0; - - /* Handle simple cases */ - if (n1 == 0 || n2 == 0) - return 0; - if (n1 == 1) - return n2; - if (n2 == 1) - return n1; - - /* - * sizeof() returns number of bytes needed for storage. - * This may be different from the actual number of useful bits. - */ - if (!bpw) { - bpw = sizeof(u_quad_t) * 8; - while (((u_quad_t)1 << (bpw-1)) == 0) - --bpw; - } - - /* - * First check the magnitude of each number. If the sum of the - * magnatude is way to high, reject the number. (If this test - * is not done then the first multiply below may overflow.) - */ - for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1) - ; - for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2) - ; - if (b1 + b2 - 2 > bpw) { - errno = ERANGE; - return (UQUAD_MAX); - } - - /* - * Decompose the multiplication to be: - * h1 = n1 & ~1 - * h2 = n2 & ~1 - * l1 = n1 & 1 - * l2 = n2 & 1 - * (h1 + l1) * (h2 + l2) - * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2) - * - * Since h1 && h2 do not have the low bit set, we can then say: - * - * (h1>>1 * h2>>1 * 4) + ... - * - * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will - * overflow. - * - * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2) - * then adding in residual amout will cause an overflow. - */ - - m = (n1 >> 1) * (n2 >> 1); - if (m >= ((u_quad_t)1 << (bpw-2))) { - errno = ERANGE; - return (UQUAD_MAX); - } - m *= 4; - - r = (n1 & n2 & 1) - + (n2 & 1) * (n1 & ~(u_quad_t)1) - + (n1 & 1) * (n2 & ~(u_quad_t)1); - - if ((u_quad_t)(m + r) < m) { - errno = ERANGE; - return (UQUAD_MAX); - } - m += r; - - return (m); -} - - -/* - * login_getcaptime() - * From the login_cap_t , get the capability , which is - * formatted as a time (e.g., "=10h3m2s"). If is not - * present in , return ; if there is an error of some kind, - * return . - */ - -rlim_t -login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *res, *ep, *oval; - int r; - rlim_t tot; - - errno = 0; - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * Look for in lc_cap. - * If it's not there (-1), return . - * If there's an error, return . - */ - - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - else if (r < 0) { - errno = ERANGE; - return error; - } - - /* "inf" and "infinity" are special cases */ - if (isinfinite(res)) - return RLIM_INFINITY; - - /* - * Now go through the string, turning something like 1h2m3s into - * an integral value. Whee. - */ - - errno = 0; - tot = 0; - oval = res; - while (*res) { - rlim_t tim = strtoq(res, &ep, 0); - rlim_t mult = 1; - - if (ep == NULL || ep == res || errno != 0) { - invalid: - syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s", - lc->lc_class, cap, oval); - errno = ERANGE; - return error; - } - /* Look for suffixes */ - switch (*ep++) { - case 0: - ep--; - break; /* end of string */ - case 's': case 'S': /* seconds */ - break; - case 'm': case 'M': /* minutes */ - mult = 60; - break; - case 'h': case 'H': /* hours */ - mult = 60L * 60L; - break; - case 'd': case 'D': /* days */ - mult = 60L * 60L * 24L; - break; - case 'w': case 'W': /* weeks */ - mult = 60L * 60L * 24L * 7L; - break; - case 'y': case 'Y': /* 365-day years */ - mult = 60L * 60L * 24L * 365L; - break; - default: - goto invalid; - } - res = ep; - tot += rmultiply(tim, mult); - if (errno) - goto invalid; - } - - return tot; -} - - -/* - * login_getcapnum() - * From the login_cap_t , extract the numerical value . - * If it is not present, return for a default, and return - * if there is an error. - * Like login_getcaptime(), only it only converts to a number, not - * to a time; "infinity" and "inf" are 'special.' - */ - -rlim_t -login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *ep, *res; - int r; - rlim_t val; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * For BSDI compatibility, try for the tag= first - */ - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) { - long lval; - /* string capability not present, so try for tag# as numeric */ - if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1) - return def; /* Not there, so return default */ - else if (r >= 0) - return (rlim_t)lval; - } - - if (r < 0) { - errno = ERANGE; - return error; - } - - if (isinfinite(res)) - return RLIM_INFINITY; - - errno = 0; - val = strtoq(res, &ep, 0); - if (ep == NULL || ep == res || errno != 0) { - syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s", - lc->lc_class, cap, res); - errno = ERANGE; - return error; - } - - return val; -} - - - -/* - * login_getcapsize() - * From the login_cap_t , extract the capability , which is - * formatted as a size (e.g., "=10M"); it can also be "infinity". - * If not present, return , or if there is an error of - * some sort. - */ - -rlim_t -login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *ep, *res, *oval; - int r; - rlim_t tot; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - else if (r < 0) { - errno = ERANGE; - return error; - } - - if (isinfinite(res)) - return RLIM_INFINITY; - - errno = 0; - tot = 0; - oval = res; - while (*res) { - rlim_t siz = strtoq(res, &ep, 0); - rlim_t mult = 1; - - if (ep == NULL || ep == res || errno != 0) { - invalid: - syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s", - lc->lc_class, cap, oval); - errno = ERANGE; - return error; - } - switch (*ep++) { - case 0: /* end of string */ - ep--; - break; - case 'b': case 'B': /* 512-byte blocks */ - mult = 512; - break; - case 'k': case 'K': /* 1024-byte Kilobytes */ - mult = 1024; - break; - case 'm': case 'M': /* 1024-k kbytes */ - mult = 1024 * 1024; - break; - case 'g': case 'G': /* 1Gbyte */ - mult = 1024 * 1024 * 1024; - break; - case 't': case 'T': /* 1TBte */ - mult = 1024LL * 1024LL * 1024LL * 1024LL; - break; - default: - goto invalid; - } - res = ep; - tot += rmultiply(siz, mult); - if (errno) - goto invalid; - } - - return tot; -} - - -/* - * login_getcapbool() - * From the login_cap_t , check for the existance of the capability - * of . Return if ->lc_cap is NULL, otherwise return - * the whether or not exists there. - */ - -int -login_getcapbool(login_cap_t *lc, const char *cap, int def) -{ - if (lc == NULL || lc->lc_cap == NULL) - return def; - return (cgetcap(lc->lc_cap, cap, ':') != NULL); -} - - -/* - * login_getstyle() - * Given a login_cap entry , and optionally a type of auth , - * and optionally a style