]>
git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lppasswd.c
2 * "$Id: lppasswd.c 5833 2006-08-16 20:05:58Z mike $"
4 * MD5 password program for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Add, change, or delete passwords from the MD5 password file.
27 * usage() - Show program usage.
31 * Include necessary headers...
40 #include <sys/types.h>
43 #include <cups/string.h>
44 #include <cups/cups.h>
45 #include <cups/i18n.h>
67 static void usage(FILE *fp
);
71 * 'main()' - Add, change, or delete passwords from the MD5 password file.
74 int /* O - Exit status */
75 main(int argc
, /* I - Number of command-line arguments */
76 char *argv
[]) /* I - Command-line arguments */
78 int i
; /* Looping var */
79 char *opt
; /* Option pointer */
80 const char *username
; /* Pointer to username */
81 const char *groupname
; /* Pointer to group name */
82 int op
; /* Operation (add, change, delete) */
83 const char *passwd
; /* Password string */
84 FILE *infile
, /* Input file */
85 *outfile
; /* Output file */
86 char line
[256], /* Line from file */
87 userline
[17], /* User from line */
88 groupline
[17], /* Group from line */
89 md5line
[33], /* MD5-sum from line */
90 md5new
[33]; /* New MD5 sum */
91 const char *root
; /* CUPS server root directory */
92 char passwdmd5
[1024], /* passwd.md5 file */
93 passwdold
[1024], /* passwd.old file */
94 passwdnew
[1024]; /* passwd.tmp file */
95 char *newpass
, /* new password */
96 *oldpass
; /* old password */
97 int flag
; /* Password check flags... */
98 int fd
; /* Password file descriptor */
99 int error
; /* Write error */
100 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
101 struct sigaction action
; /* Signal action */
102 #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
108 * Check to see if stdin, stdout, and stderr are still open...
111 if (fcntl(0, F_GETFD
, &i
) ||
112 fcntl(1, F_GETFD
, &i
) ||
113 fcntl(2, F_GETFD
, &i
))
116 * No, return exit status 2 and don't try to send any output since
117 * someone is trying to bypass the security on the server.
124 * Find the server directory...
126 * We use the CUPS_SERVERROOT environment variable when we are running
127 * as root or when lppasswd is not setuid...
130 if ((root
= getenv("CUPS_SERVERROOT")) == NULL
||
131 (getuid() != geteuid() && getuid()))
132 root
= CUPS_SERVERROOT
;
134 snprintf(passwdmd5
, sizeof(passwdmd5
), "%s/passwd.md5", root
);
135 snprintf(passwdold
, sizeof(passwdold
), "%s/passwd.old", root
);
136 snprintf(passwdnew
, sizeof(passwdnew
), "%s/passwd.new", root
);
139 * Find the default system group...
142 if (getgrnam(CUPS_DEFAULT_GROUP
))
143 groupname
= CUPS_DEFAULT_GROUP
;
145 groupname
= "unknown";
153 * Parse command-line options...
156 for (i
= 1; i
< argc
; i
++)
157 if (argv
[i
][0] == '-')
158 for (opt
= argv
[i
] + 1; *opt
; opt
++)
164 case 'x' : /* Delete */
167 case 'g' : /* Group */
174 case 'h' : /* Help */
177 default : /* Bad option */
187 * See if we are trying to add or delete a password when we aren't logged in
191 if (getuid() && getuid() != geteuid() && (op
!= CHANGE
|| username
))
193 _cupsLangPuts(stderr
,
194 _("lppasswd: Only root can add or delete passwords!\n"));
199 * Fill in missing info...
203 username
= cupsUser();
205 oldpass
= newpass
= NULL
;
208 * Obtain old and new password _before_ locking the database
209 * to keep users from locking the file indefinitely.
212 if (op
== CHANGE
&& getuid())
214 if ((passwd
= cupsGetPassword(_("Enter old password:"))) == NULL
)
217 if ((oldpass
= strdup(passwd
)) == NULL
)
219 _cupsLangPrintf(stderr
,
220 _("lppasswd: Unable to copy password string: %s\n"),
227 * Now get the new password, if necessary...
232 if ((passwd
= cupsGetPassword(_("Enter password:"))) == NULL
)
235 if ((newpass
= strdup(passwd
)) == NULL
)
237 _cupsLangPrintf(stderr
,
238 _("lppasswd: Unable to copy password string: %s\n"),
243 if ((passwd
= cupsGetPassword(_("Enter password again:"))) == NULL
)
246 if (strcmp(passwd
, newpass
) != 0)
248 _cupsLangPuts(stderr
,
249 _("lppasswd: Sorry, passwords don't match!\n"));
254 * Check that the password contains at least one letter and number.
259 for (passwd
= newpass
; *passwd
; passwd
++)
260 if (isdigit(*passwd
& 255))
262 else if (isalpha(*passwd
& 255))
266 * Only allow passwords that are at least 6 chars, have a letter and
267 * a number, and don't contain the username.
270 if (strlen(newpass
) < 6 || strstr(newpass
, username
) != NULL
|| flag
!= 3)
272 _cupsLangPuts(stderr
,
273 _("lppasswd: Sorry, password rejected.\n"
274 "Your password must be at least 6 characters long, "
276 "your username, and must contain at least one letter "
283 * Ignore SIGHUP, SIGINT, SIGTERM, and SIGXFSZ (if defined) for the
284 * remainder of the time so that we won't end up with bogus password
289 # if defined(HAVE_SIGSET)
290 sigset(SIGHUP
, SIG_IGN
);
291 sigset(SIGINT
, SIG_IGN
);
292 sigset(SIGTERM
, SIG_IGN
);
294 sigset(SIGXFSZ
, SIG_IGN
);
295 # endif /* SIGXFSZ */
296 # elif defined(HAVE_SIGACTION)
297 memset(&action
, 0, sizeof(action
));
298 action
.sa_handler
= SIG_IGN
;
300 sigaction(SIGHUP
, &action
, NULL
);
301 sigaction(SIGINT
, &action
, NULL
);
302 sigaction(SIGTERM
, &action
, NULL
);
304 sigaction(SIGXFSZ
, &action
, NULL
);
305 # endif /* SIGXFSZ */
307 signal(SIGHUP
, SIG_IGN
);
308 signal(SIGINT
, SIG_IGN
);
309 signal(SIGTERM
, SIG_IGN
);
311 signal(SIGXFSZ
, SIG_IGN
);
312 # endif /* SIGXFSZ */
317 * Open the output file.
320 if ((fd
= open(passwdnew
, O_WRONLY
| O_CREAT
| O_EXCL
, 0400)) < 0)
323 _cupsLangPuts(stderr
, _("lppasswd: Password file busy!\n"));
325 _cupsLangPrintf(stderr
,
326 _("lppasswd: Unable to open password file: %s\n"),
332 if ((outfile
= fdopen(fd
, "w")) == NULL
)
334 _cupsLangPrintf(stderr
,
335 _("lppasswd: Unable to open password file: %s\n"),
343 setbuf(outfile
, NULL
);
346 * Open the existing password file and create a new one...
349 infile
= fopen(passwdmd5
, "r");
350 if (infile
== NULL
&& errno
!= ENOENT
&& op
!= ADD
)
352 _cupsLangPrintf(stderr
,
353 _("lppasswd: Unable to open password file: %s\n"),
364 * Read lines from the password file; the format is:
366 * username:group:MD5-sum
376 while (fgets(line
, sizeof(line
), infile
) != NULL
)
378 if (sscanf(line
, "%16[^:]:%16[^:]:%32s", userline
, groupline
, md5line
) != 3)
381 if (strcmp(username
, userline
) == 0 &&
382 strcmp(groupname
, groupline
) == 0)
385 if (fputs(line
, outfile
) == EOF
)
387 _cupsLangPrintf(stderr
,
388 _("lppasswd: Unable to write to password file: %s\n"),
397 while (fgets(line
, sizeof(line
), infile
) != NULL
)
398 if (fputs(line
, outfile
) == EOF
)
400 _cupsLangPrintf(stderr
,
401 _("lppasswd: Unable to write to password file: %s\n"),
410 (strcmp(username
, userline
) || strcmp(groupname
, groupline
)))
412 _cupsLangPrintf(stderr
,
413 _("lppasswd: user \"%s\" and group \"%s\" do not exist.\n"),
414 username
, groupname
);
417 else if (op
!= DELETE
)
420 strcmp(httpMD5(username
, "CUPS", oldpass
, md5new
), md5line
) != 0)
422 _cupsLangPuts(stderr
,
423 _("lppasswd: Sorry, password doesn't match!\n"));
428 snprintf(line
, sizeof(line
), "%s:%s:%s\n", username
, groupname
,
429 httpMD5(username
, "CUPS", newpass
, md5new
));
430 if (fputs(line
, outfile
) == EOF
)
432 _cupsLangPrintf(stderr
,
433 _("lppasswd: Unable to write to password file: %s\n"),
447 if (fclose(outfile
) == EOF
)
451 * Error out gracefully as needed...
456 _cupsLangPuts(stderr
, _("lppasswd: Password file not updated!\n"));
464 * Save old passwd file
468 if (link(passwdmd5
, passwdold
) && errno
!= ENOENT
)
470 _cupsLangPrintf(stderr
,
471 _("lppasswd: failed to backup old password file: %s\n"),
478 * Install new password file
481 if (rename(passwdnew
, passwdmd5
) < 0)
483 _cupsLangPrintf(stderr
,
484 _("lppasswd: failed to rename password file: %s\n"),
495 * 'usage()' - Show program usage.
499 usage(FILE *fp
) /* I - File to send usage to */
502 _cupsLangPuts(fp
, _("Usage: lppasswd [-g groupname]\n"));
505 _("Usage: lppasswd [-g groupname] [username]\n"
506 " lppasswd [-g groupname] -a [username]\n"
507 " lppasswd [-g groupname] -x [username]\n"));
514 * End of "$Id: lppasswd.c 5833 2006-08-16 20:05:58Z mike $".