]> arthur.barton.de Git - ngircd-alex.git/commitdiff
Add pam.{c|h} to project and implement PAM_Authenticate() function
authorAlexander Barton <alex@barton.de>
Mon, 12 Jul 2010 10:53:08 +0000 (12:53 +0200)
committerAlexander Barton <alex@barton.de>
Mon, 12 Jul 2010 10:53:08 +0000 (12:53 +0200)
src/ngircd/Makefile.am
src/ngircd/pam.c [new file with mode: 0644]
src/ngircd/pam.h [new file with mode: 0644]

index 2bce2924a644d64bbd4e2196312c297f16dc0869..4c9d9fa09c1ce5401b720b57dbee3f6d1e8349ad 100644 (file)
@@ -21,7 +21,7 @@ sbin_PROGRAMS = ngircd
 ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
        conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
        irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
 ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
        conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
        irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
-       match.c op.c numeric.c parse.c proc.c rendezvous.c resolve.c
+       match.c op.c numeric.c pam.c parse.c proc.c rendezvous.c resolve.c
 
 ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
 
 
 ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
 
@@ -30,7 +30,7 @@ ngircd_LDADD = -lngportab -lngtool -lngipaddr
 noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conf-ssl.h conn.h \
        conn-func.h conn-ssl.h conn-zip.h hash.h io.h irc.h irc-channel.h \
        irc-info.h irc-login.h irc-mode.h irc-op.h irc-oper.h irc-server.h \
 noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conf-ssl.h conn.h \
        conn-func.h conn-ssl.h conn-zip.h hash.h io.h irc.h irc-channel.h \
        irc-info.h irc-login.h irc-mode.h irc-op.h irc-oper.h irc-server.h \
-       irc-write.h lists.h log.h match.h numeric.h op.h parse.h proc.h \
+       irc-write.h lists.h log.h match.h numeric.h op.h pam.h parse.h proc.h \
        rendezvous.h resolve.h defines.h messages.h
 
 clean-local:
        rendezvous.h resolve.h defines.h messages.h
 
 clean-local:
diff --git a/src/ngircd/pam.c b/src/ngircd/pam.c
new file mode 100644 (file)
index 0000000..e6d25bc
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * PAM User Authentification
+ */
+
+#include "portab.h"
+
+#ifdef PAM
+
+#include "imp.h"
+#include <assert.h>
+
+#include "defines.h"
+#include "log.h"
+#include "conn.h"
+#include "client.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SECURITY_PAM_APPL_H
+#include <security/pam_appl.h>
+#endif
+
+#ifdef HAVE_PAM_PAM_APPL_H
+#include <pam/pam_appl.h>
+#endif
+
+#include "exp.h"
+#include "pam.h"
+
+static char *password;
+
+/**
+ * PAM "conversation function".
+ * This is a callback function used by the PAM library to get the password.
+ * Please see the PAM documentation for details :-)
+ */
+static int
+password_conversation(int num_msg, const struct pam_message **msg,
+                     struct pam_response **resp, void *appdata_ptr) {
+       LogDebug("PAM: conv(%d, %d, '%s', '%s')",
+                num_msg, msg[0]->msg_style, msg[0]->msg, appdata_ptr);
+
+       /* Can we deal with this request? */
+       if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
+               Log(LOG_ERR, "PAM: Unexpected PAM conversation '%d:%s'!",
+                   msg[0]->msg_style, msg[0]->msg);
+               return PAM_CONV_ERR;
+       }
+
+       if (!appdata_ptr) {
+               /* Sometimes appdata_ptr gets lost!? */
+               appdata_ptr = password;
+       }
+
+       /* Duplicate password ("application data") for the PAM library */
+       *resp = calloc(num_msg, sizeof(struct pam_response));
+       if (!*resp) {
+               Log(LOG_ERR, "PAM: Out of memory!");
+               return PAM_CONV_ERR;
+       }
+
+       (*resp)[0].resp = strdup((char *)appdata_ptr);
+       (*resp)[0].resp_retcode = 0;
+
+       return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
+}
+
+/**
+ * PAM "conversation" structure.
+ */
+static struct pam_conv conv = {
+       &password_conversation,
+       NULL
+};
+
+/**
+ * Authenticate a connectiong client using PAM.
+ * @param Client The client to authenticate.
+ * @return true when authentication succeeded, false otherwise.
+ */
+GLOBAL bool
+PAM_Authenticate(CLIENT *Client) {
+       pam_handle_t *pam;
+       int retval = PAM_SUCCESS;
+
+       LogDebug("PAM: Authenticate \"%s\" (%s) ...",
+                Client_OrigUser(Client), Client_Mask(Client));
+
+       /* Set supplied client password */
+       if (password)
+               free(password);
+       password = strdup(Client_Password(Client));
+       conv.appdata_ptr = password;
+
+       /* Initialize PAM */
+       retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam);
+       if (retval != PAM_SUCCESS) {
+               Log(LOG_ERR, "PAM: Failed to create authenticator! (%d)", retval);
+               return false;
+       }
+
+       pam_set_item(pam, PAM_RUSER, Client_User(Client));
+       pam_set_item(pam, PAM_RHOST, Client_Hostname(Client));
+#ifdef HAVE_PAM_FAIL_DELAY
+       pam_fail_delay(pam, 0);
+#endif
+
+       /* PAM authentication ... */
+       retval = pam_authenticate(pam, 0);
+
+       /* Success? */
+       if (retval == PAM_SUCCESS)
+               Log(LOG_INFO, "PAM: Authenticated \"%s\" (%s).",
+                   Client_OrigUser(Client), Client_Mask(Client));
+       else
+               Log(LOG_ERR, "PAM: Error on \"%s\" (%s): %s",
+                   Client_OrigUser(Client), Client_Mask(Client),
+                   pam_strerror(pam, retval));
+
+       /* Free PAM structures */
+       if (pam_end(pam, retval) != PAM_SUCCESS)
+               Log(LOG_ERR, "PAM: Failed to release authenticator!");
+
+       return (retval == PAM_SUCCESS);
+}
+
+#endif /* PAM */
+
+/* -eof- */
diff --git a/src/ngircd/pam.h b/src/ngircd/pam.h
new file mode 100644 (file)
index 0000000..74b838d
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * PAM User Authentification (header)
+ */
+
+#ifdef PAM
+
+#ifndef __pam_h__
+#define __pam_h__
+
+GLOBAL bool PAM_Authenticate PARAMS((CLIENT *Client));
+
+#endif /* __pam_h__ */
+
+#endif /* PAM */
+
+/* -eof- */