10061c6a5Schristos /*
20061c6a5Schristos * Copyright (c) 2000,2002 Todd C. Miller <Todd.Miller@courtesan.com>
30061c6a5Schristos *
40061c6a5Schristos * Permission to use, copy, modify, and distribute this software for any
50061c6a5Schristos * purpose with or without fee is hereby granted, provided that the above
60061c6a5Schristos * copyright notice and this permission notice appear in all copies.
70061c6a5Schristos *
80061c6a5Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
90061c6a5Schristos * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
100061c6a5Schristos * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
110061c6a5Schristos * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
120061c6a5Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
130061c6a5Schristos * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
140061c6a5Schristos * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
150061c6a5Schristos */
160061c6a5Schristos
170061c6a5Schristos /*
180061c6a5Schristos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
190061c6a5Schristos *
200061c6a5Schristos * Permission to use, copy, modify, and distribute this software for any
210061c6a5Schristos * purpose with or without fee is hereby granted, provided that the above
220061c6a5Schristos * copyright notice and this permission notice appear in all copies.
230061c6a5Schristos *
240061c6a5Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
250061c6a5Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
260061c6a5Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
270061c6a5Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
280061c6a5Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
290061c6a5Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
300061c6a5Schristos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
310061c6a5Schristos */
32*032a4398Schristos #include <sys/cdefs.h>
330061c6a5Schristos #if !defined(lint) && !defined(LINT)
34*032a4398Schristos #if 0
350061c6a5Schristos static char rcsid[] = "Id: pw_dup.c,v 1.2 2004/01/23 18:56:43 vixie Exp";
36*032a4398Schristos #else
37*032a4398Schristos __RCSID("$NetBSD: pw_dup.c,v 1.2 2010/05/06 18:53:17 christos Exp $");
38*032a4398Schristos #endif
390061c6a5Schristos #endif
400061c6a5Schristos
410061c6a5Schristos #include <sys/param.h>
420061c6a5Schristos
430061c6a5Schristos #if !defined(OpenBSD) || OpenBSD < 200105
440061c6a5Schristos
450061c6a5Schristos #include <pwd.h>
460061c6a5Schristos #include <stdlib.h>
470061c6a5Schristos #include <stdio.h>
480061c6a5Schristos #include <string.h>
49*032a4398Schristos #include <bitstring.h>
500061c6a5Schristos
510061c6a5Schristos #include "config.h"
52*032a4398Schristos #include "macros.h"
53*032a4398Schristos #include "structs.h"
54*032a4398Schristos #include "funcs.h"
550061c6a5Schristos
560061c6a5Schristos struct passwd *
pw_dup(const struct passwd * pw)570061c6a5Schristos pw_dup(const struct passwd *pw) {
580061c6a5Schristos char *cp;
59*032a4398Schristos size_t nsize, psize, gsize, dsize, ssize, total;
60*032a4398Schristos #ifdef LOGIN_CAP
61*032a4398Schristos size_t csize;
62*032a4398Schristos #endif
630061c6a5Schristos struct passwd *newpw;
640061c6a5Schristos
650061c6a5Schristos /* Allocate in one big chunk for easy freeing */
660061c6a5Schristos total = sizeof(struct passwd);
670061c6a5Schristos if (pw->pw_name) {
680061c6a5Schristos nsize = strlen(pw->pw_name) + 1;
690061c6a5Schristos total += nsize;
70*032a4398Schristos } else
71*032a4398Schristos nsize = 0;
720061c6a5Schristos if (pw->pw_passwd) {
730061c6a5Schristos psize = strlen(pw->pw_passwd) + 1;
740061c6a5Schristos total += psize;
75*032a4398Schristos } else
76*032a4398Schristos psize = 0;
770061c6a5Schristos #ifdef LOGIN_CAP
780061c6a5Schristos if (pw->pw_class) {
790061c6a5Schristos csize = strlen(pw->pw_class) + 1;
800061c6a5Schristos total += csize;
81*032a4398Schristos } else
82*032a4398Schristos csize = 0;
830061c6a5Schristos #endif /* LOGIN_CAP */
840061c6a5Schristos if (pw->pw_gecos) {
850061c6a5Schristos gsize = strlen(pw->pw_gecos) + 1;
860061c6a5Schristos total += gsize;
87*032a4398Schristos } else
88*032a4398Schristos gsize = 0;
890061c6a5Schristos if (pw->pw_dir) {
900061c6a5Schristos dsize = strlen(pw->pw_dir) + 1;
910061c6a5Schristos total += dsize;
92*032a4398Schristos } else
93*032a4398Schristos dsize = 0;
940061c6a5Schristos if (pw->pw_shell) {
950061c6a5Schristos ssize = strlen(pw->pw_shell) + 1;
960061c6a5Schristos total += ssize;
97*032a4398Schristos } else
98*032a4398Schristos ssize = 0;
99*032a4398Schristos if ((newpw = malloc(total)) == NULL)
1000061c6a5Schristos return (NULL);
101*032a4398Schristos cp = (char *)(void *)newpw;
1020061c6a5Schristos
1030061c6a5Schristos /*
1040061c6a5Schristos * Copy in passwd contents and make strings relative to space
1050061c6a5Schristos * at the end of the buffer.
1060061c6a5Schristos */
1070061c6a5Schristos (void)memcpy(newpw, pw, sizeof(struct passwd));
1080061c6a5Schristos cp += sizeof(struct passwd);
1090061c6a5Schristos if (pw->pw_name) {
1100061c6a5Schristos (void)memcpy(cp, pw->pw_name, nsize);
1110061c6a5Schristos newpw->pw_name = cp;
1120061c6a5Schristos cp += nsize;
1130061c6a5Schristos }
1140061c6a5Schristos if (pw->pw_passwd) {
1150061c6a5Schristos (void)memcpy(cp, pw->pw_passwd, psize);
1160061c6a5Schristos newpw->pw_passwd = cp;
1170061c6a5Schristos cp += psize;
1180061c6a5Schristos }
1190061c6a5Schristos #ifdef LOGIN_CAP
1200061c6a5Schristos if (pw->pw_class) {
1210061c6a5Schristos (void)memcpy(cp, pw->pw_class, csize);
1220061c6a5Schristos newpw->pw_class = cp;
1230061c6a5Schristos cp += csize;
1240061c6a5Schristos }
1250061c6a5Schristos #endif /* LOGIN_CAP */
1260061c6a5Schristos if (pw->pw_gecos) {
1270061c6a5Schristos (void)memcpy(cp, pw->pw_gecos, gsize);
1280061c6a5Schristos newpw->pw_gecos = cp;
1290061c6a5Schristos cp += gsize;
1300061c6a5Schristos }
1310061c6a5Schristos if (pw->pw_dir) {
1320061c6a5Schristos (void)memcpy(cp, pw->pw_dir, dsize);
1330061c6a5Schristos newpw->pw_dir = cp;
1340061c6a5Schristos cp += dsize;
1350061c6a5Schristos }
1360061c6a5Schristos if (pw->pw_shell) {
1370061c6a5Schristos (void)memcpy(cp, pw->pw_shell, ssize);
1380061c6a5Schristos newpw->pw_shell = cp;
1390061c6a5Schristos cp += ssize;
1400061c6a5Schristos }
1410061c6a5Schristos
1420061c6a5Schristos return (newpw);
1430061c6a5Schristos }
1440061c6a5Schristos
1450061c6a5Schristos #endif /* !OpenBSD || OpenBSD < 200105 */
146