]>
git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lppasswd.c
2 * "$Id: lppasswd.c 6649 2007-07-11 21:46:42Z mike $"
4 * MD5 password program for CUPS.
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * main() - Add, change, or delete passwords from the MD5 password file.
18 * usage() - Show program usage.
22 * Include necessary headers...
25 #include <cups/cups-private.h>
26 #include <cups/md5-private.h>
29 #include <sys/types.h>
51 static void usage(FILE *fp
);
55 * 'main()' - Add, change, or delete passwords from the MD5 password file.
58 int /* O - Exit status */
59 main(int argc
, /* I - Number of command-line arguments */
60 char *argv
[]) /* I - Command-line arguments */
62 int i
; /* Looping var */
63 char *opt
; /* Option pointer */
64 const char *username
; /* Pointer to username */
65 const char *groupname
; /* Pointer to group name */
66 int op
; /* Operation (add, change, delete) */
67 const char *passwd
; /* Password string */
68 FILE *infile
, /* Input file */
69 *outfile
; /* Output file */
70 char line
[256], /* Line from file */
71 userline
[17], /* User from line */
72 groupline
[17], /* Group from line */
73 md5line
[33], /* MD5-sum from line */
74 md5new
[33]; /* New MD5 sum */
75 char passwdmd5
[1024], /* passwd.md5 file */
76 passwdold
[1024], /* passwd.old file */
77 passwdnew
[1024]; /* passwd.tmp file */
78 char *newpass
, /* new password */
79 *oldpass
; /* old password */
80 int flag
; /* Password check flags... */
81 int fd
; /* Password file descriptor */
82 int error
; /* Write error */
83 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
84 cups_lang_t
*lang
; /* Language info */
85 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
86 struct sigaction action
; /* Signal action */
87 #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
91 lang
= cupsLangDefault();
94 * Check to see if stdin, stdout, and stderr are still open...
97 if (fcntl(0, F_GETFD
, &i
) ||
98 fcntl(1, F_GETFD
, &i
) ||
99 fcntl(2, F_GETFD
, &i
))
102 * No, return exit status 2 and don't try to send any output since
103 * someone is trying to bypass the security on the server.
110 * Find the server directory...
113 snprintf(passwdmd5
, sizeof(passwdmd5
), "%s/passwd.md5", cg
->cups_serverroot
);
114 snprintf(passwdold
, sizeof(passwdold
), "%s/passwd.old", cg
->cups_serverroot
);
115 snprintf(passwdnew
, sizeof(passwdnew
), "%s/passwd.new", cg
->cups_serverroot
);
118 * Find the default system group...
121 if (getgrnam(CUPS_DEFAULT_GROUP
))
122 groupname
= CUPS_DEFAULT_GROUP
;
124 groupname
= "unknown";
132 * Parse command-line options...
135 for (i
= 1; i
< argc
; i
++)
136 if (argv
[i
][0] == '-')
137 for (opt
= argv
[i
] + 1; *opt
; opt
++)
143 case 'x' : /* Delete */
146 case 'g' : /* Group */
153 case 'h' : /* Help */
156 default : /* Bad option */
166 * See if we are trying to add or delete a password when we aren't logged in
170 if (getuid() && getuid() != geteuid() && (op
!= CHANGE
|| username
))
172 _cupsLangPuts(stderr
,
173 _("lppasswd: Only root can add or delete passwords\n"));
178 * Fill in missing info...
182 username
= cupsUser();
184 oldpass
= newpass
= NULL
;
187 * Obtain old and new password _before_ locking the database
188 * to keep users from locking the file indefinitely.
191 if (op
== CHANGE
&& getuid())
193 if ((passwd
= cupsGetPassword(_("Enter old password:"))) == NULL
)
196 if ((oldpass
= strdup(passwd
)) == NULL
)
198 _cupsLangPrintf(stderr
,
199 _("lppasswd: Unable to copy password string: %s\n"),
206 * Now get the new password, if necessary...
211 if ((passwd
= cupsGetPassword(
212 _cupsLangString(lang
, _("Enter password:")))) == NULL
)
215 if ((newpass
= strdup(passwd
)) == NULL
)
217 _cupsLangPrintf(stderr
,
218 _("lppasswd: Unable to copy password string: %s\n"),
223 if ((passwd
= cupsGetPassword(
224 _cupsLangString(lang
, _("Enter password again:")))) == NULL
)
227 if (strcmp(passwd
, newpass
) != 0)
229 _cupsLangPuts(stderr
,
230 _("lppasswd: Sorry, passwords don't match\n"));
235 * Check that the password contains at least one letter and number.
240 for (passwd
= newpass
; *passwd
; passwd
++)
241 if (isdigit(*passwd
& 255))
243 else if (isalpha(*passwd
& 255))
247 * Only allow passwords that are at least 6 chars, have a letter and
248 * a number, and don't contain the username.
251 if (strlen(newpass
) < 6 || strstr(newpass
, username
) != NULL
|| flag
!= 3)
253 _cupsLangPuts(stderr
,
254 _("lppasswd: Sorry, password rejected.\n"
255 "Your password must be at least 6 characters long, "
257 "your username, and must contain at least one letter "
264 * Ignore SIGHUP, SIGINT, SIGTERM, and SIGXFSZ (if defined) for the
265 * remainder of the time so that we won't end up with bogus password
270 # if defined(HAVE_SIGSET)
271 sigset(SIGHUP
, SIG_IGN
);
272 sigset(SIGINT
, SIG_IGN
);
273 sigset(SIGTERM
, SIG_IGN
);
275 sigset(SIGXFSZ
, SIG_IGN
);
276 # endif /* SIGXFSZ */
277 # elif defined(HAVE_SIGACTION)
278 memset(&action
, 0, sizeof(action
));
279 action
.sa_handler
= SIG_IGN
;
281 sigaction(SIGHUP
, &action
, NULL
);
282 sigaction(SIGINT
, &action
, NULL
);
283 sigaction(SIGTERM
, &action
, NULL
);
285 sigaction(SIGXFSZ
, &action
, NULL
);
286 # endif /* SIGXFSZ */
288 signal(SIGHUP
, SIG_IGN
);
289 signal(SIGINT
, SIG_IGN
);
290 signal(SIGTERM
, SIG_IGN
);
292 signal(SIGXFSZ
, SIG_IGN
);
293 # endif /* SIGXFSZ */
298 * Open the output file.
301 if ((fd
= open(passwdnew
, O_WRONLY
| O_CREAT
| O_EXCL
, 0400)) < 0)
304 _cupsLangPuts(stderr
, _("lppasswd: Password file busy\n"));
306 _cupsLangPrintf(stderr
,
307 _("lppasswd: Unable to open password file: %s\n"),
313 if ((outfile
= fdopen(fd
, "w")) == NULL
)
315 _cupsLangPrintf(stderr
,
316 _("lppasswd: Unable to open password file: %s\n"),
324 setbuf(outfile
, NULL
);
327 * Open the existing password file and create a new one...
330 infile
= fopen(passwdmd5
, "r");
331 if (infile
== NULL
&& errno
!= ENOENT
&& op
!= ADD
)
333 _cupsLangPrintf(stderr
,
334 _("lppasswd: Unable to open password file: %s\n"),
345 * Read lines from the password file; the format is:
347 * username:group:MD5-sum
357 while (fgets(line
, sizeof(line
), infile
) != NULL
)
359 if (sscanf(line
, "%16[^:]:%16[^:]:%32s", userline
, groupline
, md5line
) != 3)
362 if (strcmp(username
, userline
) == 0 &&
363 strcmp(groupname
, groupline
) == 0)
366 if (fputs(line
, outfile
) == EOF
)
368 _cupsLangPrintf(stderr
,
369 _("lppasswd: Unable to write to password file: %s\n"),
378 while (fgets(line
, sizeof(line
), infile
) != NULL
)
379 if (fputs(line
, outfile
) == EOF
)
381 _cupsLangPrintf(stderr
,
382 _("lppasswd: Unable to write to password file: %s\n"),
391 (strcmp(username
, userline
) || strcmp(groupname
, groupline
)))
393 _cupsLangPrintf(stderr
,
394 _("lppasswd: user \"%s\" and group \"%s\" do not exist.\n"),
395 username
, groupname
);
398 else if (op
!= DELETE
)
401 strcmp(httpMD5(username
, "CUPS", oldpass
, md5new
), md5line
) != 0)
403 _cupsLangPuts(stderr
,
404 _("lppasswd: Sorry, password doesn't match\n"));
409 snprintf(line
, sizeof(line
), "%s:%s:%s\n", username
, groupname
,
410 httpMD5(username
, "CUPS", newpass
, md5new
));
411 if (fputs(line
, outfile
) == EOF
)
413 _cupsLangPrintf(stderr
,
414 _("lppasswd: Unable to write to password file: %s\n"),
428 if (fclose(outfile
) == EOF
)
432 * Error out gracefully as needed...
437 _cupsLangPuts(stderr
, _("lppasswd: Password file not updated\n"));
445 * Save old passwd file
449 if (link(passwdmd5
, passwdold
) && errno
!= ENOENT
)
451 _cupsLangPrintf(stderr
,
452 _("lppasswd: failed to backup old password file: %s\n"),
459 * Install new password file
462 if (rename(passwdnew
, passwdmd5
) < 0)
464 _cupsLangPrintf(stderr
,
465 _("lppasswd: failed to rename password file: %s\n"),
476 * 'usage()' - Show program usage.
480 usage(FILE *fp
) /* I - File to send usage to */
483 _cupsLangPuts(fp
, _("Usage: lppasswd [-g groupname]\n"));
486 _("Usage: lppasswd [-g groupname] [username]\n"
487 " lppasswd [-g groupname] -a [username]\n"
488 " lppasswd [-g groupname] -x [username]\n"));
495 * End of "$Id: lppasswd.c 6649 2007-07-11 21:46:42Z mike $".