summaryrefslogtreecommitdiffstats
path: root/src/ckpasswd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ckpasswd.c')
-rw-r--r--src/ckpasswd.c368
1 files changed, 0 insertions, 368 deletions
diff --git a/src/ckpasswd.c b/src/ckpasswd.c
deleted file mode 100644
index 9dbdbcf..0000000
--- a/src/ckpasswd.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* $Id: ckpasswd.c 7565 2006-08-28 02:42:54Z eagle $
-**
-** The default username/password authenticator.
-**
-** This program is intended to be run by nnrpd and handle usernames and
-** passwords. It can authenticate against a regular flat file (the type
-** managed by htpasswd), a DBM file, the system password file or shadow file,
-** or PAM.
-*/
-
-/* Used for unused parameters to silence gcc warnings. */
-#define UNUSED __attribute__((__unused__))
-
-/* Make available the bool type. */
-#if INN_HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# undef true
-# undef false
-# define true (1)
-# define false (0)
-# ifndef __cplusplus
-# define bool int
-# endif
-#endif /* INN_HAVE_STDBOOL_H */
-
-#include <stdlib.h>
-#include <string.h>
-#include <crypt.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <getopt.h>
-
-#define DB_DBM_HSEARCH 1
-#include <db.h>
-#define OPT_DBM "d:"
-
-#if HAVE_GETSPNAM
-# include <shadow.h>
-# define OPT_SHADOW "s"
-#else
-# define OPT_SHADOW ""
-#endif
-
-/* The functions are actually macros so that we can pick up the file and line
- number information for debugging error messages without the user having to
- pass those in every time. */
-#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__)
-#define xmalloc(size) x_malloc((size), __FILE__, __LINE__)
-#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__)
-#define xstrdup(p) x_strdup((p), __FILE__, __LINE__)
-#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__)
-
-#include <security/pam_appl.h>
-
-/* Holds the authentication information from nnrpd. */
-struct auth_info {
- char *username;
- char *password;
-};
-
-/*
-** The PAM conversation function.
-**
-** Since we already have all the information and can't ask the user
-** questions, we can't quite follow the real PAM protocol. Instead, we just
-** return the password in response to every question that PAM asks. There
-** appears to be no generic way to determine whether the message in question
-** is indeed asking for the password....
-**
-** This function allocates an array of struct pam_response to return to the
-** PAM libraries that's never freed. For this program, this isn't much of an
-** issue, since it will likely only be called once and then the program will
-** exit. This function uses malloc and strdup instead of xmalloc and xstrdup
-** intentionally so that the PAM conversation will be closed cleanly if we
-** run out of memory rather than simply terminated.
-**
-** appdata_ptr contains the password we were given.
-*/
-static int pass_conv(int num_msg, const struct pam_message **msgm UNUSED, struct pam_response **response, void *appdata_ptr)
-{
- int i;
-
- *response = malloc(num_msg * sizeof(struct pam_response));
- if (*response == NULL)
- return PAM_CONV_ERR;
- for (i = 0; i < num_msg; i++) {
- (*response)[i].resp = strdup((char *)appdata_ptr);
- (*response)[i].resp_retcode = 0;
- }
- return PAM_SUCCESS;
-}
-
-
-/*
-** Authenticate a user via PAM.
-**
-** Attempts to authenticate a user with PAM, returning true if the user
-** successfully authenticates and false otherwise. Note that this function
-** doesn't attempt to handle any remapping of the authenticated user by the
-** PAM stack, but just assumes that the authenticated user was the same as
-** the username given.
-**
-** Right now, all failures are handled via die. This may be worth revisiting
-** in case we want to try other authentication methods if this fails for a
-** reason other than the system not having PAM support.
-*/
-
-static bool auth_pam(const char *username, char *password)
-{
- pam_handle_t *pamh;
- struct pam_conv conv;
- int status;
-
- conv.conv = pass_conv;
- conv.appdata_ptr = password;
- status = pam_start("nnrpd", username, &conv, &pamh);
- if (status != PAM_SUCCESS)
- die("pam_start failed: %s", pam_strerror(pamh, status));
- status = pam_authenticate(pamh, PAM_SILENT);
- if (status != PAM_SUCCESS)
- die("pam_authenticate failed: %s", pam_strerror(pamh, status));
- status = pam_acct_mgmt(pamh, PAM_SILENT);
- if (status != PAM_SUCCESS)
- die("pam_acct_mgmt failed: %s", pam_strerror(pamh, status));
- status = pam_end(pamh, status);
- if (status != PAM_SUCCESS)
- die("pam_end failed: %s", pam_strerror(pamh, status));
-
- /* If we get to here, the user successfully authenticated. */
- return true;
-}
-
-
-/*
-** Try to get a password out of a dbm file. The dbm file should have the
-** username for the key and the crypted password as the value. The crypted
-** password, if found, is returned as a newly allocated string; otherwise,
-** NULL is returned.
-*/
-#if !(defined(HAVE_DBM) || defined(HAVE_BDB_DBM))
-static char *
-password_dbm(char *user UNUSED, const char *file UNUSED)
-{
- return NULL;
-}
-#else
-static char *
-password_dbm(char *name, const char *file)
-{
- datum key, value;
- DBM *database;
- char *password;
-
- database = dbm_open(file, O_RDONLY, 0600);
- if (database == NULL)
- return NULL;
- key.dptr = name;
- key.dsize = strlen(name);
- value = dbm_fetch(database, key);
- if (value.dptr == NULL) {
- dbm_close(database);
- return NULL;
- }
- password = xmalloc(value.dsize + 1);
- strlcpy(password, value.dptr, value.dsize + 1);
- dbm_close(database);
- return password;
-}
-#endif /* HAVE_DBM || HAVE_BDB_DBM */
-
-
-/*
-** Try to get a password out of the system /etc/shadow file. The crypted
-** password, if found, is returned as a newly allocated string; otherwise,
-** NULL is returned.
-*/
-#if !HAVE_GETSPNAM
-static char *
-password_shadow(const char *user UNUSED)
-{
- return NULL;
-}
-#else
-static char *
-password_shadow(const char *user)
-{
- struct spwd *spwd;
-
- spwd = getspnam(user);
- if (spwd != NULL)
- return xstrdup(spwd->sp_pwdp);
- return NULL;
-}
-#endif /* HAVE_GETSPNAM */
-
-
-/*
-** Try to get a password out of the system password file. The crypted
-** password, if found, is returned as a newly allocated string; otherwise,
-** NULL is returned.
-*/
-static char *
-password_system(const char *username)
-{
- struct passwd *pwd;
-
- pwd = getpwnam(username);
- if (pwd != NULL)
- return xstrdup(pwd->pw_passwd);
- return NULL;
-}
-
-
-/*
-** Try to get the name of a user's primary group out of the system group
-** file. The group, if found, is returned as a newly allocated string;
-** otherwise, NULL is returned. If the username is not found, NULL is
-** returned.
-*/
-static char *
-group_system(const char *username)
-{
- struct passwd *pwd;
- struct group *gr;
-
- pwd = getpwnam(username);
- if (pwd == NULL)
- return NULL;
- gr = getgrgid(pwd->pw_gid);
- if (gr == NULL)
- return NULL;
- return xstrdup(gr->gr_name);
-}
-
-
-/*
-** Output username (and group, if desired) in correct return format.
-*/
-static void
-output_user(const char *username, bool wantgroup)
-{
- if (wantgroup) {
- char *group = group_system(username);
- if (group == NULL)
- die("group info for user %s not available", username);
- printf("User:%s@%s\n", username, group);
- }
- else
- printf("User:%s\n", username);
-}
-
-
-/*
-** Main routines.
-**
-** We handle the variences between systems with #if blocks above, so that
-** this code can look fairly clean.
-*/
-
-int
-main(int argc, char *argv[])
-{
- enum authtype { AUTH_NONE, AUTH_SHADOW, AUTH_FILE, AUTH_DBM };
-
- int opt;
- enum authtype type = AUTH_NONE;
- bool wantgroup = false;
- const char *filename = NULL;
- struct auth_info *authinfo = NULL;
- char *password = NULL;
-
- //message_program_name = "ckpasswd";
-
- while ((opt = getopt(argc, argv, "gf:u:p:" OPT_DBM OPT_SHADOW)) != -1) {
- switch (opt) {
- case 'g':
- if (type == AUTH_DBM || type == AUTH_FILE)
- die("-g option is incompatible with -d or -f");
- wantgroup = true;
- break;
- case 'd':
- if (type != AUTH_NONE)
- die("only one of -s, -f, or -d allowed");
- if (wantgroup)
- die("-g option is incompatible with -d or -f");
- type = AUTH_DBM;
- filename = optarg;
- break;
- case 'f':
- if (type != AUTH_NONE)
- die("only one of -s, -f, or -d allowed");
- if (wantgroup)
- die("-g option is incompatible with -d or -f");
- type = AUTH_FILE;
- filename = optarg;
- break;
- case 's':
- if (type != AUTH_NONE)
- die("only one of -s, -f, or -d allowed");
- type = AUTH_SHADOW;
- break;
- case 'u':
- if (authinfo == NULL) {
- authinfo = xmalloc(sizeof(struct auth_info));
- authinfo->password = NULL;
- }
- authinfo->username = optarg;
- break;
- case 'p':
- if (authinfo == NULL) {
- authinfo = xmalloc(sizeof(struct auth_info));
- authinfo->username = NULL;
- }
- authinfo->password = optarg;
- break;
- default:
- exit(1);
- }
- }
- if (argc != optind)
- die("extra arguments given");
- if (authinfo != NULL && authinfo->username == NULL)
- die("-u option is required if -p option is given");
- if (authinfo != NULL && authinfo->password == NULL)
- die("-p option is required if -u option is given");
-
-// /* Unless a username or password was given on the command line, assume
-// we're being run by nnrpd. */
-// if (authinfo == NULL)
-// authinfo = get_auth_info(stdin);
-// if (authinfo == NULL)
-// die("no authentication information from nnrpd");
-// if (authinfo->username[0] == '\0')
-// die("null username");
-
- /* Run the appropriate authentication routines. */
- switch (type) {
- case AUTH_SHADOW:
- password = password_shadow(authinfo->username);
- if (password == NULL)
- password = password_system(authinfo->username);
- break;
-// case AUTH_FILE:
-// password = password_file(authinfo->username, filename);
-// break;
- case AUTH_DBM:
- password = password_dbm(authinfo->username, filename);
- break;
- case AUTH_NONE:
- if (auth_pam(authinfo->username, authinfo->password)) {
- output_user(authinfo->username, wantgroup);
- exit(0);
- }
- password = password_system(authinfo->username);
- break;
- }
-
- if (password == NULL)
- die("user %s unknown", authinfo->username);
- if (strcmp(password, crypt(authinfo->password, password)) != 0)
- die("invalid password for user %s", authinfo->username);
-
- /* The password matched. */
- output_user(authinfo->username, wantgroup);
- exit(0);
-}