1 /* $NetBSD: openpam_check_owner_perms.c,v 1.3 2017/05/06 19:50:09 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 Dag-Erling Smørgrav 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $OpenPAM: openpam_check_owner_perms.c 938 2017-04-30 21:34:42Z des $ 32 */ 33 34 #ifdef HAVE_CONFIG_H 35 # include "config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 __RCSID("$NetBSD: openpam_check_owner_perms.c,v 1.3 2017/05/06 19:50:09 christos Exp $"); 40 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 44 #include <errno.h> 45 #include <limits.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <security/pam_appl.h> 51 52 #include "openpam_impl.h" 53 54 /* 55 * OpenPAM internal 56 * 57 * Verify that the file or directory referenced by the given descriptor is 58 * owned by either root or the arbitrator and that it is not writable by 59 * group or other. 60 */ 61 62 int 63 openpam_check_desc_owner_perms(const char *name, int fd) 64 { 65 uid_t root, arbitrator; 66 struct stat sb; 67 int serrno; 68 69 root = 0; 70 arbitrator = geteuid(); 71 if (fstat(fd, &sb) != 0) { 72 serrno = errno; 73 openpam_log(PAM_LOG_ERROR, "%s: %s", name, strerror(errno)); 74 errno = serrno; 75 return (-1); 76 } 77 if (!S_ISREG(sb.st_mode)) { 78 openpam_log(PAM_LOG_ERROR, 79 "%s: not a regular file", name); 80 errno = EINVAL; 81 return (-1); 82 } 83 if ((sb.st_uid != root && sb.st_uid != arbitrator) || 84 (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { 85 openpam_log(PAM_LOG_ERROR, 86 "%s: insecure ownership or permissions", name); 87 errno = EPERM; 88 return (-1); 89 } 90 return (0); 91 } 92 93 /* 94 * OpenPAM internal 95 * 96 * Verify that a file or directory and all components of the path leading 97 * up to it are owned by either root or the arbitrator and that they are 98 * not writable by group or other. 99 * 100 * Note that openpam_check_desc_owner_perms() should be used instead if 101 * possible to avoid a race between the ownership / permission check and 102 * the actual open(). 103 */ 104 105 int 106 openpam_check_path_owner_perms(const char *path) 107 { 108 uid_t root, arbitrator; 109 char pathbuf[PATH_MAX]; 110 struct stat sb; 111 size_t len; 112 int serrno, tip; 113 114 tip = 1; 115 root = 0; 116 arbitrator = geteuid(); 117 if (realpath(path, pathbuf) == NULL) 118 return (-1); 119 len = strlen(pathbuf); 120 while (len > 0) { 121 if (stat(pathbuf, &sb) != 0) { 122 if (errno != ENOENT) { 123 serrno = errno; 124 openpam_log(PAM_LOG_ERROR, "%s: %m", pathbuf); 125 errno = serrno; 126 } 127 return (-1); 128 } 129 if (tip && !S_ISREG(sb.st_mode)) { 130 openpam_log(PAM_LOG_ERROR, 131 "%s: not a regular file", pathbuf); 132 errno = EINVAL; 133 return (-1); 134 } 135 if ((sb.st_uid != root && sb.st_uid != arbitrator) || 136 (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { 137 openpam_log(PAM_LOG_ERROR, 138 "%s: insecure ownership or permissions", pathbuf); 139 errno = EPERM; 140 return (-1); 141 } 142 while (--len > 0 && pathbuf[len] != '/') 143 pathbuf[len] = '\0'; 144 tip = 0; 145 } 146 return (0); 147 } 148 149 /* 150 * NOPARSE 151 */ 152