Commit | Line | Data |
---|---|---|
dc647f87 | 1 | #include <stdlib.h> |
2febc19a | 2 | #include <stdio.h> |
dc647f87 | 3 | #include <unistd.h> |
2febc19a DC |
4 | #include <string.h> |
5 | #include <stdarg.h> | |
6 | #include <malloc.h> | |
dc647f87 DC |
7 | #include <krb5.h> |
8 | ||
9 | #define PAM_SM_AUTH | |
10 | ||
11 | #include <security/pam_modules.h> | |
12 | ||
2febc19a DC |
13 | #define DEF_INSTANCE "autologin" |
14 | ||
15 | struct options | |
16 | { | |
17 | char *realm; | |
18 | char *instance; | |
19 | char *keytab; | |
20 | int debug; | |
21 | }; | |
22 | ||
23 | struct data | |
24 | { | |
25 | krb5_context ctx; | |
26 | krb5_ccache cc; | |
27 | krb5_principal me; | |
28 | }; | |
29 | ||
30 | static void log(int prio, char *format, ...) | |
31 | { | |
32 | va_list args; | |
33 | char buf[1024]; | |
34 | ||
35 | va_start(args, format); | |
36 | snprintf(buf, sizeof(buf), "pam_krb5auto[%i]: %s", getpid(), format); | |
37 | vsyslog(prio, buf, args); | |
38 | va_end(args); | |
39 | } | |
40 | ||
41 | static struct options *parseopts(int argc, const char **argv) | |
42 | { | |
43 | int i; | |
44 | struct options *opts; | |
45 | ||
46 | opts = malloc(sizeof(*opts)); | |
47 | memset(opts, 0, sizeof(*opts)); | |
48 | for(i = 0; i < argc; i++) { | |
49 | if(!strncmp(argv[i], "realm=", 6)) | |
50 | opts->realm = strdup(argv[i] + 6); | |
51 | if(!strncmp(argv[i], "instance=", 9)) | |
52 | opts->instance = strdup(argv[i] + 9); | |
53 | if(!strncmp(argv[i], "keytab=", 7)) | |
54 | opts->keytab = strdup(argv[i] + 7); | |
55 | if(!strcmp(argv[i], "debug")) | |
56 | opts->debug = 1; | |
57 | } | |
58 | return(opts); | |
59 | } | |
60 | ||
61 | static void freeopts(struct options *opts) | |
62 | { | |
63 | if(opts->realm != NULL) | |
64 | free(opts->realm); | |
65 | if(opts->instance != NULL) | |
66 | free(opts->instance); | |
67 | if(opts->keytab != NULL) | |
68 | free(opts->keytab); | |
69 | free(opts); | |
70 | } | |
71 | ||
72 | static void freedata(struct data *data) | |
73 | { | |
74 | if(data->me != NULL) | |
75 | krb5_free_principal(data->ctx, data->me); | |
76 | if(data->ctx != NULL) | |
77 | krb5_free_context(data->ctx); | |
78 | free(data); | |
79 | } | |
80 | ||
81 | static void cleanupdata(pam_handle_t *pamh, struct data *data, int error_status) | |
82 | { | |
83 | freedata(data); | |
84 | } | |
85 | ||
86 | static struct data *getdata(pam_handle_t *pamh, struct options *opts) | |
87 | { | |
88 | int ret; | |
89 | struct data *data; | |
90 | char buf[1024]; | |
91 | const char *user, *instance; | |
92 | ||
93 | data = NULL; | |
94 | pam_get_data(pamh, "krb5auto-data", (const void **)&data); | |
95 | if(data == NULL) { | |
96 | if(opts->debug) | |
97 | log(LOG_DEBUG, "creating new instance"); | |
98 | data = malloc(sizeof(*data)); | |
99 | memset(data, 0, sizeof(*data)); | |
100 | if((ret = krb5_init_context(&data->ctx)) != 0) { | |
101 | log(LOG_CRIT, "could not create krb5 context: %s", error_message(ret)); | |
102 | freedata(data); | |
103 | return(NULL); | |
104 | } | |
105 | pam_get_user(pamh, &user, NULL); | |
106 | if(opts->instance) | |
107 | instance = opts->instance; | |
108 | else | |
109 | instance = DEF_INSTANCE; | |
110 | if(opts->realm) | |
111 | snprintf(buf, sizeof(buf), "%s/%s@%s", user, instance, opts->realm); | |
112 | else | |
113 | snprintf(buf, sizeof(buf), "%s/%s", user, instance); | |
114 | if((ret = krb5_parse_name(data->ctx, buf, &data->me)) != 0) { | |
115 | log(LOG_ERR, "could not parse principal name `%s': %s", buf, error_message(ret)); | |
116 | freedata(data); | |
117 | return(NULL); | |
118 | } | |
119 | pam_set_data(pamh, "krb5auto-data", data, (void (*)(pam_handle_t *, void *, int))cleanupdata); | |
120 | } | |
121 | return(data); | |
122 | } | |
123 | ||
124 | static void savecreds(struct options *opts, struct data *data) | |
125 | { | |
126 | } | |
127 | ||
128 | PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) | |
129 | { | |
130 | return(PAM_IGNORE); | |
131 | } | |
132 | ||
133 | PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) | |
134 | { | |
135 | struct options *opts; | |
136 | struct data *data; | |
137 | ||
138 | opts = parseopts(argc, argv); | |
139 | data = getdata(pamh, opts); | |
140 | if(data == NULL) { | |
141 | log(LOG_ERR, "could not get data, erroring out"); | |
142 | return(PAM_SERVICE_ERR); | |
143 | } | |
144 | if(flags & PAM_ESTABLISH_CRED) { | |
145 | savecreds(opts, data); | |
146 | } | |
147 | freeopts(opts); | |
148 | return(PAM_IGNORE); | |
149 | } | |
dc647f87 DC |
150 | |
151 | /* | |
152 | * Local Variables: | |
153 | * compile-command: "gcc -Wall -g --shared -fPIC -o pam_krb5auto.so pam_krb5auto.c" | |
154 | * End: | |
155 | */ |