su.c revision 1.21 1 1.21 kleink /* $NetBSD: su.c,v 1.21 1998/04/02 11:13:33 kleink Exp $ */
2 1.12 christos
3 1.1 cgd /*
4 1.1 cgd * Copyright (c) 1988 The Regents of the University of California.
5 1.1 cgd * All rights reserved.
6 1.1 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.1 cgd * 3. All advertising materials mentioning features or use of this software
16 1.1 cgd * must display the following acknowledgement:
17 1.1 cgd * This product includes software developed by the University of
18 1.1 cgd * California, Berkeley and its contributors.
19 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
20 1.1 cgd * may be used to endorse or promote products derived from this software
21 1.1 cgd * without specific prior written permission.
22 1.1 cgd *
23 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 cgd * SUCH DAMAGE.
34 1.1 cgd */
35 1.1 cgd
36 1.19 lukem #include <sys/cdefs.h>
37 1.1 cgd #ifndef lint
38 1.19 lukem __COPYRIGHT(
39 1.19 lukem "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
40 1.19 lukem All rights reserved.\n");
41 1.1 cgd #endif /* not lint */
42 1.1 cgd
43 1.1 cgd #ifndef lint
44 1.12 christos #if 0
45 1.13 tls static char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94";*/
46 1.12 christos #else
47 1.21 kleink __RCSID("$NetBSD: su.c,v 1.21 1998/04/02 11:13:33 kleink Exp $");
48 1.12 christos #endif
49 1.1 cgd #endif /* not lint */
50 1.1 cgd
51 1.1 cgd #include <sys/param.h>
52 1.1 cgd #include <sys/time.h>
53 1.1 cgd #include <sys/resource.h>
54 1.13 tls #include <err.h>
55 1.11 christos #include <errno.h>
56 1.17 lukem #include <grp.h>
57 1.17 lukem #include <paths.h>
58 1.17 lukem #include <pwd.h>
59 1.17 lukem #include <stdio.h>
60 1.17 lukem #include <skey.h>
61 1.7 jtc #include <stdlib.h>
62 1.1 cgd #include <string.h>
63 1.17 lukem #include <syslog.h>
64 1.21 kleink #include <time.h>
65 1.17 lukem #include <tzfile.h>
66 1.1 cgd #include <unistd.h>
67 1.1 cgd
68 1.1 cgd #ifdef KERBEROS
69 1.1 cgd #include <kerberosIV/des.h>
70 1.1 cgd #include <kerberosIV/krb.h>
71 1.1 cgd #include <netdb.h>
72 1.1 cgd
73 1.1 cgd #define ARGSTR "-Kflm"
74 1.1 cgd
75 1.1 cgd int use_kerberos = 1;
76 1.11 christos
77 1.11 christos static int kerberos __P((char *, char *, int));
78 1.11 christos static int koktologin __P((char *, char *, char *));
79 1.11 christos
80 1.1 cgd #else
81 1.1 cgd #define ARGSTR "-flm"
82 1.1 cgd #endif
83 1.1 cgd
84 1.18 lukem #ifndef SUGROUP
85 1.18 lukem #define SUGROUP "wheel"
86 1.18 lukem #endif
87 1.18 lukem
88 1.11 christos
89 1.11 christos int main __P((int, char **));
90 1.11 christos
91 1.11 christos static int chshell __P((char *));
92 1.11 christos static char *ontty __P((void));
93 1.11 christos
94 1.2 sef
95 1.7 jtc int
96 1.1 cgd main(argc, argv)
97 1.1 cgd int argc;
98 1.1 cgd char **argv;
99 1.1 cgd {
100 1.11 christos extern char *__progname;
101 1.1 cgd extern char **environ;
102 1.13 tls struct passwd *pwd;
103 1.17 lukem char *p;
104 1.1 cgd struct group *gr;
105 1.17 lukem struct timeval tp;
106 1.11 christos uid_t ruid;
107 1.1 cgd int asme, ch, asthem, fastlogin, prio;
108 1.1 cgd enum { UNSET, YES, NO } iscsh = UNSET;
109 1.8 mycroft char *user, *shell, *avshell, *username, *cleanenv[10], **np;
110 1.8 mycroft char shellbuf[MAXPATHLEN], avshellbuf[MAXPATHLEN];
111 1.1 cgd
112 1.1 cgd asme = asthem = fastlogin = 0;
113 1.17 lukem shell = NULL;
114 1.19 lukem while ((ch = getopt(argc, argv, ARGSTR)) != -1)
115 1.1 cgd switch((char)ch) {
116 1.1 cgd #ifdef KERBEROS
117 1.1 cgd case 'K':
118 1.1 cgd use_kerberos = 0;
119 1.1 cgd break;
120 1.1 cgd #endif
121 1.1 cgd case 'f':
122 1.1 cgd fastlogin = 1;
123 1.1 cgd break;
124 1.1 cgd case '-':
125 1.1 cgd case 'l':
126 1.1 cgd asme = 0;
127 1.1 cgd asthem = 1;
128 1.1 cgd break;
129 1.1 cgd case 'm':
130 1.1 cgd asme = 1;
131 1.1 cgd asthem = 0;
132 1.1 cgd break;
133 1.1 cgd case '?':
134 1.1 cgd default:
135 1.11 christos (void)fprintf(stderr,
136 1.11 christos "Usage: %s [%s] [login [shell arguments]]\n",
137 1.11 christos __progname, ARGSTR);
138 1.1 cgd exit(1);
139 1.1 cgd }
140 1.1 cgd argv += optind;
141 1.1 cgd
142 1.1 cgd errno = 0;
143 1.1 cgd prio = getpriority(PRIO_PROCESS, 0);
144 1.1 cgd if (errno)
145 1.1 cgd prio = 0;
146 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, -2);
147 1.1 cgd openlog("su", LOG_CONS, 0);
148 1.1 cgd
149 1.1 cgd /* get current login name and shell */
150 1.1 cgd ruid = getuid();
151 1.1 cgd username = getlogin();
152 1.1 cgd if (username == NULL || (pwd = getpwnam(username)) == NULL ||
153 1.1 cgd pwd->pw_uid != ruid)
154 1.1 cgd pwd = getpwuid(ruid);
155 1.1 cgd if (pwd == NULL) {
156 1.13 tls errx(1, "who are you?");
157 1.1 cgd }
158 1.1 cgd username = strdup(pwd->pw_name);
159 1.1 cgd if (asme)
160 1.1 cgd if (pwd->pw_shell && *pwd->pw_shell)
161 1.15 mrg shell = strncpy(shellbuf, pwd->pw_shell,
162 1.15 mrg sizeof(shellbuf) + 1);
163 1.1 cgd else {
164 1.1 cgd shell = _PATH_BSHELL;
165 1.1 cgd iscsh = NO;
166 1.1 cgd }
167 1.1 cgd
168 1.1 cgd /* get target login information, default to root */
169 1.1 cgd user = *argv ? *argv : "root";
170 1.2 sef np = *argv ? argv : argv-1;
171 1.2 sef
172 1.1 cgd if ((pwd = getpwnam(user)) == NULL) {
173 1.13 tls errx(1, "unknown login %s", user);
174 1.1 cgd }
175 1.1 cgd
176 1.1 cgd if (ruid) {
177 1.1 cgd #ifdef KERBEROS
178 1.1 cgd if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
179 1.1 cgd #endif
180 1.1 cgd {
181 1.18 lukem /* Only allow those in group SUGROUP to su to root,
182 1.18 lukem but only if that group has any members.
183 1.18 lukem If SUGROUP has no members, allow anyone to su root */
184 1.18 lukem if (pwd->pw_uid == 0 &&
185 1.18 lukem (gr = getgrnam(SUGROUP)) && *gr->gr_mem) {
186 1.18 lukem char **g;
187 1.18 lukem
188 1.18 lukem for (g = gr->gr_mem; ; g++) {
189 1.18 lukem if (*g == NULL)
190 1.18 lukem errx(1,
191 1.18 lukem "you are not listed in the correct secondary group (%s) to su %s.",
192 1.18 lukem SUGROUP, user);
193 1.18 lukem if (strcmp(username, *g) == 0)
194 1.17 lukem break;
195 1.18 lukem }
196 1.1 cgd }
197 1.1 cgd /* if target requires a password, verify it */
198 1.1 cgd if (*pwd->pw_passwd) {
199 1.1 cgd p = getpass("Password:");
200 1.10 deraadt #ifdef SKEY
201 1.10 deraadt if (strcasecmp(p, "s/key") == 0) {
202 1.13 tls if (skey_haskey(user))
203 1.13 tls errx(1, "Sorry, you have no s/key.");
204 1.13 tls else {
205 1.10 deraadt if (skey_authenticate(user)) {
206 1.10 deraadt goto badlogin;
207 1.10 deraadt }
208 1.10 deraadt }
209 1.10 deraadt
210 1.10 deraadt } else
211 1.10 deraadt #endif
212 1.1 cgd if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
213 1.10 deraadt badlogin:
214 1.1 cgd fprintf(stderr, "Sorry\n");
215 1.1 cgd syslog(LOG_AUTH|LOG_WARNING,
216 1.1 cgd "BAD SU %s to %s%s", username,
217 1.1 cgd user, ontty());
218 1.1 cgd exit(1);
219 1.1 cgd }
220 1.1 cgd }
221 1.1 cgd }
222 1.1 cgd }
223 1.1 cgd
224 1.1 cgd if (asme) {
225 1.1 cgd /* if asme and non-standard target shell, must be root */
226 1.13 tls if (!chshell(pwd->pw_shell) && ruid)
227 1.13 tls errx(1,"permission denied (shell).");
228 1.1 cgd } else if (pwd->pw_shell && *pwd->pw_shell) {
229 1.1 cgd shell = pwd->pw_shell;
230 1.1 cgd iscsh = UNSET;
231 1.1 cgd } else {
232 1.1 cgd shell = _PATH_BSHELL;
233 1.1 cgd iscsh = NO;
234 1.1 cgd }
235 1.1 cgd
236 1.17 lukem if ((p = strrchr(shell, '/')) != NULL)
237 1.9 cgd avshell = p+1;
238 1.9 cgd else
239 1.9 cgd avshell = shell;
240 1.9 cgd
241 1.1 cgd /* if we're forking a csh, we want to slightly muck the args */
242 1.9 cgd if (iscsh == UNSET)
243 1.11 christos iscsh = strstr(avshell, "csh") ? YES : NO;
244 1.1 cgd
245 1.1 cgd /* set permissions */
246 1.13 tls if (setgid(pwd->pw_gid) < 0)
247 1.13 tls err(1, "setgid");
248 1.13 tls if (initgroups(user, pwd->pw_gid))
249 1.13 tls errx(1, "initgroups failed");
250 1.13 tls if (setuid(pwd->pw_uid) < 0)
251 1.13 tls err(1, "setuid");
252 1.1 cgd
253 1.1 cgd if (!asme) {
254 1.1 cgd if (asthem) {
255 1.1 cgd p = getenv("TERM");
256 1.8 mycroft cleanenv[0] = NULL;
257 1.1 cgd environ = cleanenv;
258 1.8 mycroft (void)setenv("PATH", _PATH_DEFPATH, 1);
259 1.11 christos if (p)
260 1.11 christos (void)setenv("TERM", p, 1);
261 1.13 tls if (chdir(pwd->pw_dir) < 0)
262 1.13 tls errx(1, "no directory");
263 1.1 cgd }
264 1.5 jtc if (asthem || pwd->pw_uid)
265 1.1 cgd (void)setenv("USER", pwd->pw_name, 1);
266 1.1 cgd (void)setenv("HOME", pwd->pw_dir, 1);
267 1.1 cgd (void)setenv("SHELL", shell, 1);
268 1.1 cgd }
269 1.1 cgd
270 1.12 christos if (iscsh == YES) {
271 1.12 christos if (fastlogin)
272 1.12 christos *np-- = "-f";
273 1.12 christos if (asme)
274 1.12 christos *np-- = "-m";
275 1.12 christos }
276 1.1 cgd
277 1.8 mycroft if (asthem) {
278 1.8 mycroft avshellbuf[0] = '-';
279 1.15 mrg (void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
280 1.8 mycroft avshell = avshellbuf;
281 1.8 mycroft } else if (iscsh == YES) {
282 1.8 mycroft /* csh strips the first character... */
283 1.8 mycroft avshellbuf[0] = '_';
284 1.15 mrg (void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
285 1.8 mycroft avshell = avshellbuf;
286 1.8 mycroft }
287 1.12 christos *np = avshell;
288 1.11 christos
289 1.17 lukem if (pwd->pw_change || pwd->pw_expire)
290 1.17 lukem (void)gettimeofday(&tp, (struct timezone *)NULL);
291 1.17 lukem if (pwd->pw_change)
292 1.17 lukem if (tp.tv_sec >= pwd->pw_change) {
293 1.17 lukem (void)printf("%s -- %s's password has expired.\n",
294 1.17 lukem (ruid ? "Sorry" : "Note"), user);
295 1.17 lukem if (ruid != 0)
296 1.17 lukem exit(1);
297 1.17 lukem } else if (pwd->pw_change - tp.tv_sec <
298 1.17 lukem _PASSWORD_WARNDAYS * SECSPERDAY)
299 1.17 lukem (void)printf("Warning: %s's password expires on %s",
300 1.17 lukem user, ctime(&pwd->pw_change));
301 1.17 lukem if (pwd->pw_expire)
302 1.17 lukem if (tp.tv_sec >= pwd->pw_expire) {
303 1.17 lukem (void)printf("%s -- %s's account has expired.\n",
304 1.17 lukem (ruid ? "Sorry" : "Note"), user);
305 1.17 lukem if (ruid != 0)
306 1.17 lukem exit(1);
307 1.17 lukem } else if (pwd->pw_expire - tp.tv_sec <
308 1.17 lukem _PASSWORD_WARNDAYS * SECSPERDAY)
309 1.17 lukem (void)printf("Warning: %s's account expires on %s",
310 1.17 lukem user, ctime(&pwd->pw_expire));
311 1.17 lukem
312 1.1 cgd if (ruid != 0)
313 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",
314 1.1 cgd username, user, ontty());
315 1.1 cgd
316 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, prio);
317 1.1 cgd
318 1.12 christos execv(shell, np);
319 1.13 tls err(1, "%s", shell);
320 1.1 cgd }
321 1.11 christos
322 1.11 christos static int
323 1.1 cgd chshell(sh)
324 1.1 cgd char *sh;
325 1.1 cgd {
326 1.13 tls char *cp;
327 1.1 cgd
328 1.1 cgd while ((cp = getusershell()) != NULL)
329 1.1 cgd if (!strcmp(cp, sh))
330 1.1 cgd return (1);
331 1.1 cgd return (0);
332 1.1 cgd }
333 1.1 cgd
334 1.11 christos static char *
335 1.1 cgd ontty()
336 1.1 cgd {
337 1.19 lukem char *p;
338 1.1 cgd static char buf[MAXPATHLEN + 4];
339 1.1 cgd
340 1.1 cgd buf[0] = 0;
341 1.17 lukem if ((p = ttyname(STDERR_FILENO)) != NULL)
342 1.15 mrg (void)snprintf(buf, sizeof buf, " on %s", p);
343 1.1 cgd return (buf);
344 1.1 cgd }
345 1.1 cgd
346 1.1 cgd #ifdef KERBEROS
347 1.11 christos static int
348 1.1 cgd kerberos(username, user, uid)
349 1.1 cgd char *username, *user;
350 1.1 cgd int uid;
351 1.1 cgd {
352 1.1 cgd KTEXT_ST ticket;
353 1.1 cgd AUTH_DAT authdata;
354 1.1 cgd struct hostent *hp;
355 1.1 cgd int kerno;
356 1.1 cgd u_long faddr;
357 1.1 cgd char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
358 1.1 cgd char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
359 1.1 cgd
360 1.1 cgd if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
361 1.1 cgd return (1);
362 1.1 cgd if (koktologin(username, lrealm, user) && !uid) {
363 1.13 tls warnx("kerberos: not in %s's ACL.", user);
364 1.1 cgd return (1);
365 1.1 cgd }
366 1.15 mrg (void)(void)snprintf(krbtkfile, sizeof krbtkfile, "%s_%s_%d", TKT_ROOT,
367 1.15 mrg user, getuid());
368 1.1 cgd
369 1.1 cgd (void)setenv("KRBTKFILE", krbtkfile, 1);
370 1.1 cgd (void)krb_set_tkt_string(krbtkfile);
371 1.1 cgd /*
372 1.1 cgd * Set real as well as effective ID to 0 for the moment,
373 1.1 cgd * to make the kerberos library do the right thing.
374 1.1 cgd */
375 1.1 cgd if (setuid(0) < 0) {
376 1.13 tls warn("setuid");
377 1.1 cgd return (1);
378 1.1 cgd }
379 1.1 cgd
380 1.1 cgd /*
381 1.1 cgd * Little trick here -- if we are su'ing to root,
382 1.1 cgd * we need to get a ticket for "xxx.root", where xxx represents
383 1.1 cgd * the name of the person su'ing. Otherwise (non-root case),
384 1.1 cgd * we need to get a ticket for "yyy.", where yyy represents
385 1.1 cgd * the name of the person being su'd to, and the instance is null
386 1.1 cgd *
387 1.1 cgd * We should have a way to set the ticket lifetime,
388 1.1 cgd * with a system default for root.
389 1.1 cgd */
390 1.1 cgd kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
391 1.1 cgd (uid == 0 ? "root" : ""), lrealm,
392 1.17 lukem "krbtgt", lrealm, DEFAULT_TKT_LIFE, 0);
393 1.1 cgd
394 1.1 cgd if (kerno != KSUCCESS) {
395 1.1 cgd if (kerno == KDC_PR_UNKNOWN) {
396 1.13 tls warnx("kerberos: principal unknown: %s.%s@%s",
397 1.1 cgd (uid == 0 ? username : user),
398 1.1 cgd (uid == 0 ? "root" : ""), lrealm);
399 1.1 cgd return (1);
400 1.1 cgd }
401 1.13 tls warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
402 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
403 1.1 cgd "BAD Kerberos SU: %s to %s%s: %s",
404 1.1 cgd username, user, ontty(), krb_err_txt[kerno]);
405 1.1 cgd return (1);
406 1.1 cgd }
407 1.1 cgd
408 1.1 cgd if (chown(krbtkfile, uid, -1) < 0) {
409 1.13 tls warn("chown");
410 1.1 cgd (void)unlink(krbtkfile);
411 1.1 cgd return (1);
412 1.1 cgd }
413 1.1 cgd
414 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, -2);
415 1.1 cgd
416 1.1 cgd if (gethostname(hostname, sizeof(hostname)) == -1) {
417 1.13 tls warn("gethostname");
418 1.1 cgd dest_tkt();
419 1.1 cgd return (1);
420 1.1 cgd }
421 1.1 cgd
422 1.1 cgd (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
423 1.1 cgd savehost[sizeof(savehost) - 1] = '\0';
424 1.1 cgd
425 1.1 cgd kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
426 1.1 cgd
427 1.1 cgd if (kerno == KDC_PR_UNKNOWN) {
428 1.13 tls warnx("Warning: TGT not verified.");
429 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
430 1.1 cgd "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
431 1.1 cgd username, user, ontty(), krb_err_txt[kerno],
432 1.1 cgd "rcmd", savehost);
433 1.1 cgd } else if (kerno != KSUCCESS) {
434 1.13 tls warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
435 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
436 1.1 cgd username, user, ontty(), krb_err_txt[kerno]);
437 1.1 cgd dest_tkt();
438 1.1 cgd return (1);
439 1.1 cgd } else {
440 1.1 cgd if (!(hp = gethostbyname(hostname))) {
441 1.13 tls warnx("can't get addr of %s", hostname);
442 1.1 cgd dest_tkt();
443 1.1 cgd return (1);
444 1.1 cgd }
445 1.13 tls memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
446 1.1 cgd
447 1.1 cgd if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
448 1.1 cgd &authdata, "")) != KSUCCESS) {
449 1.13 tls warnx("kerberos: unable to verify rcmd ticket: %s\n",
450 1.1 cgd krb_err_txt[kerno]);
451 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
452 1.1 cgd "failed su: %s to %s%s: %s", username,
453 1.1 cgd user, ontty(), krb_err_txt[kerno]);
454 1.1 cgd dest_tkt();
455 1.1 cgd return (1);
456 1.1 cgd }
457 1.1 cgd }
458 1.1 cgd return (0);
459 1.1 cgd }
460 1.1 cgd
461 1.11 christos static int
462 1.1 cgd koktologin(name, realm, toname)
463 1.1 cgd char *name, *realm, *toname;
464 1.1 cgd {
465 1.19 lukem AUTH_DAT *kdata;
466 1.1 cgd AUTH_DAT kdata_st;
467 1.1 cgd
468 1.1 cgd kdata = &kdata_st;
469 1.13 tls memset((char *)kdata, 0, sizeof(*kdata));
470 1.15 mrg (void)strncpy(kdata->pname, name, sizeof(kdata->pname) - 1);
471 1.16 explorer (void)strncpy(kdata->pinst,
472 1.15 mrg ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof(kdata->pinst) - 1);
473 1.16 explorer (void)strncpy(kdata->prealm, realm, sizeof(kdata->prealm) - 1);
474 1.1 cgd return (kuserok(kdata, toname));
475 1.1 cgd }
476 1.1 cgd #endif
477