summaryrefslogtreecommitdiffstats
path: root/contrib/openpam/lib/openpam_configure.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/openpam/lib/openpam_configure.c')
-rw-r--r--contrib/openpam/lib/openpam_configure.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/contrib/openpam/lib/openpam_configure.c b/contrib/openpam/lib/openpam_configure.c
new file mode 100644
index 0000000..8c12e10
--- /dev/null
+++ b/contrib/openpam/lib/openpam_configure.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by ThinkSec AS and
+ * NAI Labs, the Security Research Division of Network Associates, Inc.
+ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+ * DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/openpam/lib/openpam_configure.c#1 $
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <security/pam_appl.h>
+
+#include "openpam_impl.h"
+
+#define PAM_CONF_STYLE 0
+#define PAM_D_STYLE 1
+#define MAX_LINE_LEN 1024
+#define MAX_OPTIONS 256
+
+static int
+openpam_read_policy_file(pam_handle_t *pamh,
+ const char *service,
+ const char *filename,
+ int style)
+{
+ char buf[MAX_LINE_LEN], *p, *q;
+ const char *optv[MAX_OPTIONS + 1];
+ int ch, chain, flag, line, optc, n, r;
+ size_t len;
+ FILE *f;
+
+ n = 0;
+
+ if ((f = fopen(filename, "r")) == NULL) {
+ openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
+ "%s: %m", filename);
+ return (0);
+ }
+ openpam_log(PAM_LOG_DEBUG, "looking for '%s' in %s",
+ service, filename);
+
+ for (line = 1; fgets(buf, MAX_LINE_LEN, f) != NULL; ++line) {
+ if ((len = strlen(buf)) == 0)
+ continue;
+
+ /* check for overflow */
+ if (buf[--len] != '\n' && !feof(f)) {
+ openpam_log(PAM_LOG_ERROR, "%s: line %d too long",
+ filename, line);
+ openpam_log(PAM_LOG_ERROR, "%s: ignoring line %d",
+ filename, line);
+ while ((ch = fgetc(f)) != EOF)
+ if (ch == '\n')
+ break;
+ continue;
+ }
+
+ /* strip comments and trailing whitespace */
+ if ((p = strchr(buf, '#')) != NULL)
+ len = p - buf ? p - buf - 1 : p - buf;
+ while (len > 0 && isspace(buf[len - 1]))
+ --len;
+ if (len == 0)
+ continue;
+ buf[len] = '\0';
+ p = q = buf;
+
+ /* check service name */
+ if (style == PAM_CONF_STYLE) {
+ for (q = p = buf; *q != '\0' && !isspace(*q); ++q)
+ /* nothing */;
+ if (*q == '\0')
+ goto syntax_error;
+ *q++ = '\0';
+ if (strcmp(p, service) != 0)
+ continue;
+ openpam_log(PAM_LOG_DEBUG, "%s: line %d matches '%s'",
+ filename, line, service);
+ }
+
+
+ /* get module type */
+ for (p = q; isspace(*p); ++p)
+ /* nothing */;
+ for (q = p; *q != '\0' && !isspace(*q); ++q)
+ /* nothing */;
+ if (q == p || *q == '\0')
+ goto syntax_error;
+ *q++ = '\0';
+ if (strcmp(p, "auth") == 0) {
+ chain = PAM_AUTH;
+ } else if (strcmp(p, "account") == 0) {
+ chain = PAM_ACCOUNT;
+ } else if (strcmp(p, "session") == 0) {
+ chain = PAM_SESSION;
+ } else if (strcmp(p, "password") == 0) {
+ chain = PAM_PASSWORD;
+ } else {
+ openpam_log(PAM_LOG_ERROR,
+ "%s: invalid module type on line %d: '%s'",
+ filename, line, p);
+ continue;
+ }
+
+ /* get control flag */
+ for (p = q; isspace(*p); ++p)
+ /* nothing */;
+ for (q = p; *q != '\0' && !isspace(*q); ++q)
+ /* nothing */;
+ if (q == p || *q == '\0')
+ goto syntax_error;
+ *q++ = '\0';
+ if (strcmp(p, "required") == 0) {
+ flag = PAM_REQUIRED;
+ } else if (strcmp(p, "requisite") == 0) {
+ flag = PAM_REQUISITE;
+ } else if (strcmp(p, "sufficient") == 0) {
+ flag = PAM_SUFFICIENT;
+ } else if (strcmp(p, "optional") == 0) {
+ flag = PAM_OPTIONAL;
+ } else {
+ openpam_log(PAM_LOG_ERROR,
+ "%s: invalid control flag on line %d: '%s'",
+ filename, line, p);
+ continue;
+ }
+
+ /* get module name */
+ for (p = q; isspace(*p); ++p)
+ /* nothing */;
+ for (q = p; *q != '\0' && !isspace(*q); ++q)
+ /* nothing */;
+ if (q == p)
+ goto syntax_error;
+
+ /* get options */
+ for (optc = 0; *q != '\0' && optc < MAX_OPTIONS; ++optc) {
+ *q++ = '\0';
+ while (isspace(*q))
+ ++q;
+ optv[optc] = q;
+ while (*q != '\0' && !isspace(*q))
+ ++q;
+ }
+ optv[optc] = NULL;
+ if (*q != '\0') {
+ *q = '\0';
+ openpam_log(PAM_LOG_ERROR,
+ "%s: too many options on line %d",
+ filename, line);
+ }
+
+ /*
+ * Finally, add the module at the end of the
+ * appropriate chain and bump the counter.
+ */
+ r = openpam_add_module(pamh, chain, flag, p, optc, optv);
+ if (r != PAM_SUCCESS)
+ return (-r);
+ ++n;
+ continue;
+ syntax_error:
+ openpam_log(PAM_LOG_ERROR, "%s: syntax error on line %d",
+ filename, line);
+ openpam_log(PAM_LOG_DEBUG, "%s: line %d: [%s]",
+ filename, line, q);
+ openpam_log(PAM_LOG_ERROR, "%s: ignoring line %d",
+ filename, line);
+ }
+
+ if (ferror(f))
+ openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
+
+ fclose(f);
+ return (n);
+}
+
+static const char *openpam_policy_path[] = {
+ "/etc/pam.d/",
+ "/etc/pam.conf",
+ "/usr/local/etc/pam.d/",
+ NULL
+};
+
+/*
+ * OpenPAM internal
+ *
+ * Configure a service
+ */
+
+int
+openpam_configure(pam_handle_t *pamh,
+ const char *service)
+{
+ const char **path;
+ char *filename;
+ size_t len;
+ int r;
+
+ for (path = openpam_policy_path; *path != NULL; ++path) {
+ len = strlen(*path);
+ if ((*path)[len - 1] == '/') {
+ filename = malloc(len + strlen(service) + 1);
+ if (filename == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
+ return (PAM_BUF_ERR);
+ }
+ strcpy(filename, *path);
+ strcat(filename, service);
+ r = openpam_read_policy_file(pamh,
+ service, filename, PAM_D_STYLE);
+ free(filename);
+ } else {
+ r = openpam_read_policy_file(pamh,
+ service, *path, PAM_CONF_STYLE);
+ }
+ if (r < 0)
+ return (-r);
+ if (r > 0)
+ return (PAM_SUCCESS);
+ }
+
+ return (PAM_SYSTEM_ERR);
+}
+
+/*
+ * NODOC
+ *
+ * Error codes:
+ * PAM_SYSTEM_ERR
+ * PAM_BUF_ERR
+ */
OpenPOWER on IntegriCloud