1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*
* Copyright (C) 2017 Cumulus Networks, Inc.
* All rights reserved.
* Author: Dave Olson <olson@cumulusnetworks.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program - see the file COPYING.
*/
/*
* This plugin implements getpwnam_r for NSS to map any user
* name to a fixed account (from the configuration file). The
* fixed account is used to get the base of the home directory,
* and for the uid and gid. All other fields are replaced, and
* the password is always returned as 'x' (disabled). The assumption
* is that any authentication and authorization will be done via PAM
* using some mechanism other than the local password file.
*
* Because it will match any account, this should always be the
* last module in /etc/nsswitch.conf for the passwd entry
*
* The home dir returned is the mapped user homedir with the last component
* replaced with the username being looked up.
*
* See nss_mapuid.c for the matching getpwuid_r for UIDs.
*/
#include "map_common.h"
#include <stdbool.h>
static const char *nssname = "nss_mapuser"; /* for syslogs */
/*
* If you aren't using glibc or a variant that supports this,
* and you have a system that supports the BSD getprogname(),
* you can replace this use with getprogname()
*/
extern const char *__progname;
/*
* This is an NSS entry point.
* We map any username given to the account listed in the configuration file
* We only fail if we can't read the configuration file, or the username
* in the configuration file can't be found in the /etc/passwd file.
* Because we always have a positive reply, it's important that this
* be the last NSS module for passwd lookups.
*/
__attribute__ ((visibility("default")))
enum nss_status _nss_mapname_getpwnam_r(const char *name, struct passwd *pw,
char *buffer, size_t buflen,
int *errnop)
{
enum nss_status status = NSS_STATUS_NOTFOUND;
struct pwbuf pbuf;
bool islocal = 0;
/*
* the useradd family will not add/mod/del users correctly with
* the mapuid functionality, so return immediately if we are
* running as part of those processes.
*/
if (__progname && (!strcmp(__progname, "useradd") ||
!strcmp(__progname, "usermod") ||
!strcmp(__progname, "userdel")))
return status;
if (nss_mapuser_config(errnop, nssname) == 1) {
syslog(LOG_NOTICE, "%s: bad configuration", nssname);
return status;
}
/*
* Ignore any name starting with tacacs[0-9] in case a
* tacplus client is installed. Cleaner than listing
* all 16 in the exclude_users list or implementing
* some form of wildcard. Also ignore our own mappeduser
* and mapped_priv_user names if set.
*/
if ((mappeduser && !strcmp(mappeduser, name)) ||
(mapped_priv_user && !strcmp(mapped_priv_user, name)))
islocal = 1;
else if (!strncmp("tacacs", name, 6) && isdigit(name[6]))
islocal = 1;
else if (exclude_users) {
char *user, *list;
list = strdup(exclude_users);
if (list) {
static const char *delim = ", \t\n";
user = strtok(list, delim);
list = NULL;
while (user) {
if (!strcmp(user, name)) {
islocal = 1;
break;
}
user = strtok(NULL, delim);
}
free(list);
}
}
if (islocal) {
if (debug > 1)
syslog(LOG_DEBUG, "%s: skipped excluded user: %s",
nssname, name);
return 2;
}
/* marshal the args for the lower level functions */
pbuf.name = (char *)name;
pbuf.pw = pw;
pbuf.buf = buffer;
pbuf.buflen = buflen;
pbuf.errnop = errnop;
if (!get_pw_mapuser(name, &pbuf))
status = NSS_STATUS_SUCCESS;
return status;
}
|