su.c revision 1.19 1 1.19 lukem /* $NetBSD: su.c,v 1.19 1997/10/19 23:31:54 lukem 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.19 lukem __RCSID("$NetBSD: su.c,v 1.19 1997/10/19 23:31:54 lukem 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.17 lukem #include <tzfile.h>
65 1.1 cgd #include <unistd.h>
66 1.1 cgd
67 1.1 cgd #ifdef KERBEROS
68 1.1 cgd #include <kerberosIV/des.h>
69 1.1 cgd #include <kerberosIV/krb.h>
70 1.1 cgd #include <netdb.h>
71 1.1 cgd
72 1.1 cgd #define ARGSTR "-Kflm"
73 1.1 cgd
74 1.1 cgd int use_kerberos = 1;
75 1.11 christos
76 1.11 christos static int kerberos __P((char *, char *, int));
77 1.11 christos static int koktologin __P((char *, char *, char *));
78 1.11 christos
79 1.1 cgd #else
80 1.1 cgd #define ARGSTR "-flm"
81 1.1 cgd #endif
82 1.1 cgd
83 1.18 lukem #ifndef SUGROUP
84 1.18 lukem #define SUGROUP "wheel"
85 1.18 lukem #endif
86 1.18 lukem
87 1.11 christos
88 1.11 christos int main __P((int, char **));
89 1.11 christos
90 1.11 christos static int chshell __P((char *));
91 1.11 christos static char *ontty __P((void));
92 1.11 christos
93 1.2 sef
94 1.7 jtc int
95 1.1 cgd main(argc, argv)
96 1.1 cgd int argc;
97 1.1 cgd char **argv;
98 1.1 cgd {
99 1.11 christos extern char *__progname;
100 1.1 cgd extern char **environ;
101 1.13 tls struct passwd *pwd;
102 1.17 lukem char *p;
103 1.1 cgd struct group *gr;
104 1.17 lukem struct timeval tp;
105 1.11 christos uid_t ruid;
106 1.1 cgd int asme, ch, asthem, fastlogin, prio;
107 1.1 cgd enum { UNSET, YES, NO } iscsh = UNSET;
108 1.8 mycroft char *user, *shell, *avshell, *username, *cleanenv[10], **np;
109 1.8 mycroft char shellbuf[MAXPATHLEN], avshellbuf[MAXPATHLEN];
110 1.1 cgd
111 1.1 cgd asme = asthem = fastlogin = 0;
112 1.17 lukem shell = NULL;
113 1.19 lukem while ((ch = getopt(argc, argv, ARGSTR)) != -1)
114 1.1 cgd switch((char)ch) {
115 1.1 cgd #ifdef KERBEROS
116 1.1 cgd case 'K':
117 1.1 cgd use_kerberos = 0;
118 1.1 cgd break;
119 1.1 cgd #endif
120 1.1 cgd case 'f':
121 1.1 cgd fastlogin = 1;
122 1.1 cgd break;
123 1.1 cgd case '-':
124 1.1 cgd case 'l':
125 1.1 cgd asme = 0;
126 1.1 cgd asthem = 1;
127 1.1 cgd break;
128 1.1 cgd case 'm':
129 1.1 cgd asme = 1;
130 1.1 cgd asthem = 0;
131 1.1 cgd break;
132 1.1 cgd case '?':
133 1.1 cgd default:
134 1.11 christos (void)fprintf(stderr,
135 1.11 christos "Usage: %s [%s] [login [shell arguments]]\n",
136 1.11 christos __progname, ARGSTR);
137 1.1 cgd exit(1);
138 1.1 cgd }
139 1.1 cgd argv += optind;
140 1.1 cgd
141 1.1 cgd errno = 0;
142 1.1 cgd prio = getpriority(PRIO_PROCESS, 0);
143 1.1 cgd if (errno)
144 1.1 cgd prio = 0;
145 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, -2);
146 1.1 cgd openlog("su", LOG_CONS, 0);
147 1.1 cgd
148 1.1 cgd /* get current login name and shell */
149 1.1 cgd ruid = getuid();
150 1.1 cgd username = getlogin();
151 1.1 cgd if (username == NULL || (pwd = getpwnam(username)) == NULL ||
152 1.1 cgd pwd->pw_uid != ruid)
153 1.1 cgd pwd = getpwuid(ruid);
154 1.1 cgd if (pwd == NULL) {
155 1.13 tls errx(1, "who are you?");
156 1.1 cgd }
157 1.1 cgd username = strdup(pwd->pw_name);
158 1.1 cgd if (asme)
159 1.1 cgd if (pwd->pw_shell && *pwd->pw_shell)
160 1.15 mrg shell = strncpy(shellbuf, pwd->pw_shell,
161 1.15 mrg sizeof(shellbuf) + 1);
162 1.1 cgd else {
163 1.1 cgd shell = _PATH_BSHELL;
164 1.1 cgd iscsh = NO;
165 1.1 cgd }
166 1.1 cgd
167 1.1 cgd /* get target login information, default to root */
168 1.1 cgd user = *argv ? *argv : "root";
169 1.2 sef np = *argv ? argv : argv-1;
170 1.2 sef
171 1.1 cgd if ((pwd = getpwnam(user)) == NULL) {
172 1.13 tls errx(1, "unknown login %s", user);
173 1.1 cgd }
174 1.1 cgd
175 1.1 cgd if (ruid) {
176 1.1 cgd #ifdef KERBEROS
177 1.1 cgd if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
178 1.1 cgd #endif
179 1.1 cgd {
180 1.18 lukem /* Only allow those in group SUGROUP to su to root,
181 1.18 lukem but only if that group has any members.
182 1.18 lukem If SUGROUP has no members, allow anyone to su root */
183 1.18 lukem if (pwd->pw_uid == 0 &&
184 1.18 lukem (gr = getgrnam(SUGROUP)) && *gr->gr_mem) {
185 1.18 lukem char **g;
186 1.18 lukem
187 1.18 lukem for (g = gr->gr_mem; ; g++) {
188 1.18 lukem if (*g == NULL)
189 1.18 lukem errx(1,
190 1.18 lukem "you are not listed in the correct secondary group (%s) to su %s.",
191 1.18 lukem SUGROUP, user);
192 1.18 lukem if (strcmp(username, *g) == 0)
193 1.17 lukem break;
194 1.18 lukem }
195 1.1 cgd }
196 1.1 cgd /* if target requires a password, verify it */
197 1.1 cgd if (*pwd->pw_passwd) {
198 1.1 cgd p = getpass("Password:");
199 1.10 deraadt #ifdef SKEY
200 1.10 deraadt if (strcasecmp(p, "s/key") == 0) {
201 1.13 tls if (skey_haskey(user))
202 1.13 tls errx(1, "Sorry, you have no s/key.");
203 1.13 tls else {
204 1.10 deraadt if (skey_authenticate(user)) {
205 1.10 deraadt goto badlogin;
206 1.10 deraadt }
207 1.10 deraadt }
208 1.10 deraadt
209 1.10 deraadt } else
210 1.10 deraadt #endif
211 1.1 cgd if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
212 1.10 deraadt badlogin:
213 1.1 cgd fprintf(stderr, "Sorry\n");
214 1.1 cgd syslog(LOG_AUTH|LOG_WARNING,
215 1.1 cgd "BAD SU %s to %s%s", username,
216 1.1 cgd user, ontty());
217 1.1 cgd exit(1);
218 1.1 cgd }
219 1.1 cgd }
220 1.1 cgd }
221 1.1 cgd }
222 1.1 cgd
223 1.1 cgd if (asme) {
224 1.1 cgd /* if asme and non-standard target shell, must be root */
225 1.13 tls if (!chshell(pwd->pw_shell) && ruid)
226 1.13 tls errx(1,"permission denied (shell).");
227 1.1 cgd } else if (pwd->pw_shell && *pwd->pw_shell) {
228 1.1 cgd shell = pwd->pw_shell;
229 1.1 cgd iscsh = UNSET;
230 1.1 cgd } else {
231 1.1 cgd shell = _PATH_BSHELL;
232 1.1 cgd iscsh = NO;
233 1.1 cgd }
234 1.1 cgd
235 1.17 lukem if ((p = strrchr(shell, '/')) != NULL)
236 1.9 cgd avshell = p+1;
237 1.9 cgd else
238 1.9 cgd avshell = shell;
239 1.9 cgd
240 1.1 cgd /* if we're forking a csh, we want to slightly muck the args */
241 1.9 cgd if (iscsh == UNSET)
242 1.11 christos iscsh = strstr(avshell, "csh") ? YES : NO;
243 1.1 cgd
244 1.1 cgd /* set permissions */
245 1.13 tls if (setgid(pwd->pw_gid) < 0)
246 1.13 tls err(1, "setgid");
247 1.13 tls if (initgroups(user, pwd->pw_gid))
248 1.13 tls errx(1, "initgroups failed");
249 1.13 tls if (setuid(pwd->pw_uid) < 0)
250 1.13 tls err(1, "setuid");
251 1.1 cgd
252 1.1 cgd if (!asme) {
253 1.1 cgd if (asthem) {
254 1.1 cgd p = getenv("TERM");
255 1.8 mycroft cleanenv[0] = NULL;
256 1.1 cgd environ = cleanenv;
257 1.8 mycroft (void)setenv("PATH", _PATH_DEFPATH, 1);
258 1.11 christos if (p)
259 1.11 christos (void)setenv("TERM", p, 1);
260 1.13 tls if (chdir(pwd->pw_dir) < 0)
261 1.13 tls errx(1, "no directory");
262 1.1 cgd }
263 1.5 jtc if (asthem || pwd->pw_uid)
264 1.1 cgd (void)setenv("USER", pwd->pw_name, 1);
265 1.1 cgd (void)setenv("HOME", pwd->pw_dir, 1);
266 1.1 cgd (void)setenv("SHELL", shell, 1);
267 1.1 cgd }
268 1.1 cgd
269 1.12 christos if (iscsh == YES) {
270 1.12 christos if (fastlogin)
271 1.12 christos *np-- = "-f";
272 1.12 christos if (asme)
273 1.12 christos *np-- = "-m";
274 1.12 christos }
275 1.1 cgd
276 1.8 mycroft if (asthem) {
277 1.8 mycroft avshellbuf[0] = '-';
278 1.15 mrg (void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
279 1.8 mycroft avshell = avshellbuf;
280 1.8 mycroft } else if (iscsh == YES) {
281 1.8 mycroft /* csh strips the first character... */
282 1.8 mycroft avshellbuf[0] = '_';
283 1.15 mrg (void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
284 1.8 mycroft avshell = avshellbuf;
285 1.8 mycroft }
286 1.12 christos *np = avshell;
287 1.11 christos
288 1.17 lukem if (pwd->pw_change || pwd->pw_expire)
289 1.17 lukem (void)gettimeofday(&tp, (struct timezone *)NULL);
290 1.17 lukem if (pwd->pw_change)
291 1.17 lukem if (tp.tv_sec >= pwd->pw_change) {
292 1.17 lukem (void)printf("%s -- %s's password has expired.\n",
293 1.17 lukem (ruid ? "Sorry" : "Note"), user);
294 1.17 lukem if (ruid != 0)
295 1.17 lukem exit(1);
296 1.17 lukem } else if (pwd->pw_change - tp.tv_sec <
297 1.17 lukem _PASSWORD_WARNDAYS * SECSPERDAY)
298 1.17 lukem (void)printf("Warning: %s's password expires on %s",
299 1.17 lukem user, ctime(&pwd->pw_change));
300 1.17 lukem if (pwd->pw_expire)
301 1.17 lukem if (tp.tv_sec >= pwd->pw_expire) {
302 1.17 lukem (void)printf("%s -- %s's account has expired.\n",
303 1.17 lukem (ruid ? "Sorry" : "Note"), user);
304 1.17 lukem if (ruid != 0)
305 1.17 lukem exit(1);
306 1.17 lukem } else if (pwd->pw_expire - tp.tv_sec <
307 1.17 lukem _PASSWORD_WARNDAYS * SECSPERDAY)
308 1.17 lukem (void)printf("Warning: %s's account expires on %s",
309 1.17 lukem user, ctime(&pwd->pw_expire));
310 1.17 lukem
311 1.1 cgd if (ruid != 0)
312 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",
313 1.1 cgd username, user, ontty());
314 1.1 cgd
315 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, prio);
316 1.1 cgd
317 1.12 christos execv(shell, np);
318 1.13 tls err(1, "%s", shell);
319 1.1 cgd }
320 1.11 christos
321 1.11 christos static int
322 1.1 cgd chshell(sh)
323 1.1 cgd char *sh;
324 1.1 cgd {
325 1.13 tls char *cp;
326 1.1 cgd
327 1.1 cgd while ((cp = getusershell()) != NULL)
328 1.1 cgd if (!strcmp(cp, sh))
329 1.1 cgd return (1);
330 1.1 cgd return (0);
331 1.1 cgd }
332 1.1 cgd
333 1.11 christos static char *
334 1.1 cgd ontty()
335 1.1 cgd {
336 1.19 lukem char *p;
337 1.1 cgd static char buf[MAXPATHLEN + 4];
338 1.1 cgd
339 1.1 cgd buf[0] = 0;
340 1.17 lukem if ((p = ttyname(STDERR_FILENO)) != NULL)
341 1.15 mrg (void)snprintf(buf, sizeof buf, " on %s", p);
342 1.1 cgd return (buf);
343 1.1 cgd }
344 1.1 cgd
345 1.1 cgd #ifdef KERBEROS
346 1.11 christos static int
347 1.1 cgd kerberos(username, user, uid)
348 1.1 cgd char *username, *user;
349 1.1 cgd int uid;
350 1.1 cgd {
351 1.1 cgd KTEXT_ST ticket;
352 1.1 cgd AUTH_DAT authdata;
353 1.1 cgd struct hostent *hp;
354 1.19 lukem char *p;
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 char *ontty(), *krb_get_phost();
360 1.1 cgd
361 1.1 cgd if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
362 1.1 cgd return (1);
363 1.1 cgd if (koktologin(username, lrealm, user) && !uid) {
364 1.13 tls warnx("kerberos: not in %s's ACL.", user);
365 1.1 cgd return (1);
366 1.1 cgd }
367 1.15 mrg (void)(void)snprintf(krbtkfile, sizeof krbtkfile, "%s_%s_%d", TKT_ROOT,
368 1.15 mrg user, getuid());
369 1.1 cgd
370 1.1 cgd (void)setenv("KRBTKFILE", krbtkfile, 1);
371 1.1 cgd (void)krb_set_tkt_string(krbtkfile);
372 1.1 cgd /*
373 1.1 cgd * Set real as well as effective ID to 0 for the moment,
374 1.1 cgd * to make the kerberos library do the right thing.
375 1.1 cgd */
376 1.1 cgd if (setuid(0) < 0) {
377 1.13 tls warn("setuid");
378 1.1 cgd return (1);
379 1.1 cgd }
380 1.1 cgd
381 1.1 cgd /*
382 1.1 cgd * Little trick here -- if we are su'ing to root,
383 1.1 cgd * we need to get a ticket for "xxx.root", where xxx represents
384 1.1 cgd * the name of the person su'ing. Otherwise (non-root case),
385 1.1 cgd * we need to get a ticket for "yyy.", where yyy represents
386 1.1 cgd * the name of the person being su'd to, and the instance is null
387 1.1 cgd *
388 1.1 cgd * We should have a way to set the ticket lifetime,
389 1.1 cgd * with a system default for root.
390 1.1 cgd */
391 1.1 cgd kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
392 1.1 cgd (uid == 0 ? "root" : ""), lrealm,
393 1.17 lukem "krbtgt", lrealm, DEFAULT_TKT_LIFE, 0);
394 1.1 cgd
395 1.1 cgd if (kerno != KSUCCESS) {
396 1.1 cgd if (kerno == KDC_PR_UNKNOWN) {
397 1.13 tls warnx("kerberos: principal unknown: %s.%s@%s",
398 1.1 cgd (uid == 0 ? username : user),
399 1.1 cgd (uid == 0 ? "root" : ""), lrealm);
400 1.1 cgd return (1);
401 1.1 cgd }
402 1.13 tls warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
403 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
404 1.1 cgd "BAD Kerberos SU: %s to %s%s: %s",
405 1.1 cgd username, user, ontty(), krb_err_txt[kerno]);
406 1.1 cgd return (1);
407 1.1 cgd }
408 1.1 cgd
409 1.1 cgd if (chown(krbtkfile, uid, -1) < 0) {
410 1.13 tls warn("chown");
411 1.1 cgd (void)unlink(krbtkfile);
412 1.1 cgd return (1);
413 1.1 cgd }
414 1.1 cgd
415 1.1 cgd (void)setpriority(PRIO_PROCESS, 0, -2);
416 1.1 cgd
417 1.1 cgd if (gethostname(hostname, sizeof(hostname)) == -1) {
418 1.13 tls warn("gethostname");
419 1.1 cgd dest_tkt();
420 1.1 cgd return (1);
421 1.1 cgd }
422 1.1 cgd
423 1.1 cgd (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
424 1.1 cgd savehost[sizeof(savehost) - 1] = '\0';
425 1.1 cgd
426 1.1 cgd kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
427 1.1 cgd
428 1.1 cgd if (kerno == KDC_PR_UNKNOWN) {
429 1.13 tls warnx("Warning: TGT not verified.");
430 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
431 1.1 cgd "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
432 1.1 cgd username, user, ontty(), krb_err_txt[kerno],
433 1.1 cgd "rcmd", savehost);
434 1.1 cgd } else if (kerno != KSUCCESS) {
435 1.13 tls warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
436 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
437 1.1 cgd username, user, ontty(), krb_err_txt[kerno]);
438 1.1 cgd dest_tkt();
439 1.1 cgd return (1);
440 1.1 cgd } else {
441 1.1 cgd if (!(hp = gethostbyname(hostname))) {
442 1.13 tls warnx("can't get addr of %s", hostname);
443 1.1 cgd dest_tkt();
444 1.1 cgd return (1);
445 1.1 cgd }
446 1.13 tls memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
447 1.1 cgd
448 1.1 cgd if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
449 1.1 cgd &authdata, "")) != KSUCCESS) {
450 1.13 tls warnx("kerberos: unable to verify rcmd ticket: %s\n",
451 1.1 cgd krb_err_txt[kerno]);
452 1.1 cgd syslog(LOG_NOTICE|LOG_AUTH,
453 1.1 cgd "failed su: %s to %s%s: %s", username,
454 1.1 cgd user, ontty(), krb_err_txt[kerno]);
455 1.1 cgd dest_tkt();
456 1.1 cgd return (1);
457 1.1 cgd }
458 1.1 cgd }
459 1.1 cgd return (0);
460 1.1 cgd }
461 1.1 cgd
462 1.11 christos static int
463 1.1 cgd koktologin(name, realm, toname)
464 1.1 cgd char *name, *realm, *toname;
465 1.1 cgd {
466 1.19 lukem AUTH_DAT *kdata;
467 1.1 cgd AUTH_DAT kdata_st;
468 1.1 cgd
469 1.1 cgd kdata = &kdata_st;
470 1.13 tls memset((char *)kdata, 0, sizeof(*kdata));
471 1.15 mrg (void)strncpy(kdata->pname, name, sizeof(kdata->pname) - 1);
472 1.16 explorer (void)strncpy(kdata->pinst,
473 1.15 mrg ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof(kdata->pinst) - 1);
474 1.16 explorer (void)strncpy(kdata->prealm, realm, sizeof(kdata->prealm) - 1);
475 1.1 cgd return (kuserok(kdata, toname));
476 1.1 cgd }
477 1.1 cgd #endif
478