This repository has been archived by the owner on Jun 5, 2018. It is now read-only.
forked from rra/pam-krb5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsupport.c
141 lines (127 loc) · 4.58 KB
/
support.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* Support functions for pam-krb5.
*
* Some general utility functions used by multiple PAM groups that aren't
* associated with any particular chunk of functionality.
*
* Copyright 2011, 2012
* The Board of Trustees of the Leland Stanford Junior University
* Copyright 2005, 2006, 2007, 2009 Russ Allbery <[email protected]>
* Copyright 2005 Andres Salomon <[email protected]>
* Copyright 1999, 2000 Frank Cusack <[email protected]>
*
* See LICENSE for licensing terms.
*/
#include <config.h>
#include <portable/krb5.h>
#include <portable/pam.h>
#include <portable/system.h>
#include <errno.h>
#include <pwd.h>
#include <internal.h>
#include <pam-util/args.h>
#include <pam-util/logging.h>
/*
* Given the PAM arguments and the user we're authenticating, see if we should
* ignore that user because they're root or have a low-numbered UID and we
* were configured to ignore such users. Returns true if we should ignore
* them, false otherwise. Ignores any fully-qualified principal names.
*/
int
pamk5_should_ignore(struct pam_args *args, PAM_CONST char *username)
{
struct passwd *pwd;
if (args->config->ignore_root && strcmp("root", username) == 0) {
putil_debug(args, "ignoring root user");
return 1;
}
if (args->config->minimum_uid > 0 && strchr(username, '@') == NULL) {
pwd = pam_modutil_getpwnam(args->pamh, username);
if (pwd != NULL && pwd->pw_uid < (uid_t) args->config->minimum_uid) {
putil_debug(args, "ignoring low-UID user (%lu < %ld)",
(unsigned long) pwd->pw_uid,
args->config->minimum_uid);
return 1;
}
}
return 0;
}
/*
* Verify the user authorization. Call krb5_kuserok if this is a local
* account, or do the krb5_aname_to_localname verification if ignore_k5login
* was requested. For non-local accounts, the principal must match the
* authentication identity.
*/
int
pamk5_authorized(struct pam_args *args)
{
struct context *ctx;
krb5_context c;
krb5_error_code retval;
int status;
struct passwd *pwd;
char kuser[65]; /* MAX_USERNAME == 65 (MIT Kerberos 1.4.1). */
if (args == NULL || args->config == NULL || args->config->ctx == NULL
|| args->config->ctx->context == NULL)
return PAM_SERVICE_ERR;
ctx = args->config->ctx;
if (ctx->name == NULL)
return PAM_SERVICE_ERR;
c = ctx->context;
/*
* If alt_auth_map was set, authorize the user if the authenticated
* principal matches the mapped principal. alt_auth_map essentially
* serves as a supplemental .k5login. PAM_SERVICE_ERR indicates fatal
* errors that should abort remaining processing; PAM_AUTH_ERR indicates
* that it just didn't match, in which case we continue to try other
* authorization methods.
*/
if (args->config->alt_auth_map != NULL) {
status = pamk5_alt_auth_verify(args);
if (status == PAM_SUCCESS || status == PAM_SERVICE_ERR)
return status;
}
/*
* If the name to which we're authenticating contains @ (is fully
* qualified), it must match the principal exactly.
*/
if (strchr(ctx->name, '@') != NULL) {
char *principal;
retval = krb5_unparse_name(c, ctx->princ, &principal);
if (retval != 0) {
putil_err_krb5(args, retval, "krb5_unparse_name failed");
return PAM_SERVICE_ERR;
}
if (strcmp(principal, ctx->name) != 0) {
putil_err(args, "user %s does not match principal %s", ctx->name,
principal);
krb5_free_unparsed_name(c, principal);
return PAM_AUTH_ERR;
}
krb5_free_unparsed_name(c, principal);
return PAM_SUCCESS;
}
/*
* Otherwise, apply either krb5_aname_to_localname or krb5_kuserok
* depending on the situation.
*/
pwd = pam_modutil_getpwnam(args->pamh, ctx->name);
if (args->config->ignore_k5login || pwd == NULL) {
retval = krb5_aname_to_localname(c, ctx->princ, sizeof(kuser), kuser);
if (retval != 0) {
putil_err_krb5(args, retval, "cannot convert principal to user");
return PAM_AUTH_ERR;
}
if (strcmp(kuser, ctx->name) != 0) {
putil_err(args, "user %s does not match local name %s", ctx->name,
kuser);
return PAM_AUTH_ERR;
}
} else {
if (!krb5_kuserok(c, ctx->princ, ctx->name)) {
putil_err(args, "krb5_kuserok for user %s failed", ctx->name);
return PAM_AUTH_ERR;
}
}
return PAM_SUCCESS;
}