Mercurial > dropbear
comparison svr-authpam.c @ 119:3394a7cb30cd private-rez
propagate of 08347df3bca787bd3621602fe2b466c85c9dc3e2 and 717950f4061f1123659ee87c7c168805af920ab7 from branch 'matt.dbclient.rez' to 'matt.dbclient.authpam'
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 12 Sep 2004 05:52:36 +0000 |
parents | 3b2a5a1c4347 |
children | 9337c9f9a607 |
comparison
equal
deleted
inserted
replaced
118:5312ca05ed48 | 119:3394a7cb30cd |
---|---|
34 #include <security/pam_appl.h> | 34 #include <security/pam_appl.h> |
35 #elif defined (HAVE_PAM_PAM_APPL_H) | 35 #elif defined (HAVE_PAM_PAM_APPL_H) |
36 #include <pam/pam_appl.h> | 36 #include <pam/pam_appl.h> |
37 #endif | 37 #endif |
38 | 38 |
39 #ifdef DROPBEAR_PAM_AUTH | |
40 | |
41 struct UserDataS { | 39 struct UserDataS { |
42 char* user; | 40 char* user; |
43 char* passwd; | 41 char* passwd; |
44 }; | 42 }; |
45 | 43 |
46 /* PAM conversation function */ | 44 /* PAM conversation function - for now we only handle one message */ |
47 int | 45 int |
48 pamConvFunc(int num_msg, | 46 pamConvFunc(int num_msg, |
49 const struct pam_message **msg, | 47 const struct pam_message **msg, |
50 struct pam_response **respp, | 48 struct pam_response **respp, |
51 void *appdata_ptr) { | 49 void *appdata_ptr) { |
52 int rc = PAM_SUCCESS; | 50 |
53 struct pam_response* resp = NULL; | 51 int rc = PAM_SUCCESS; |
54 struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr; | 52 struct pam_response* resp = NULL; |
55 | 53 struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr; |
56 /* tbd only handles one msg */ | 54 const char* message = (*msg)->msg; |
57 | 55 |
58 switch((*msg)->msg_style) { | 56 TRACE(("enter pamConvFunc")); |
59 case PAM_PROMPT_ECHO_OFF: | 57 TRACE(("msg_style is %d", (*msg)->msg_style)); |
60 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_PROMPT_ECHO_OFF: (*msg)->msg=\"%s\"", (*msg)->msg); | 58 if (message) { |
61 | 59 TRACE(("message is '%s'", message)); |
62 if (strcmp((*msg)->msg, "Password:") == 0) { | 60 } else { |
63 resp = (struct pam_response*) malloc(sizeof(struct pam_response)); | 61 TRACE(("null message")); |
64 resp->resp = (char*) strdup(userDatap->passwd); | 62 } |
65 /* dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_PROMPT_ECHO_ON: userDatap->passwd=\"%s\"", userDatap->passwd); */ | 63 |
66 resp->resp_retcode = 0; | 64 switch((*msg)->msg_style) { |
67 (*respp) = resp; | 65 |
68 } | 66 case PAM_PROMPT_ECHO_OFF: |
69 else { | 67 |
70 dropbear_log(LOG_WARNING, "pamConvFunc(): PAM_PROMPT_ECHO_OFF: unrecognized prompt, (*msg)->msg=\"%s\"", (*msg)->msg); | 68 if (strcmp(message, "Password:") != 0) { |
71 rc = PAM_CONV_ERR; | 69 TRACE(("PAM_PROMPT_ECHO_OFF: unrecognized prompt")); |
72 } | 70 rc = PAM_CONV_ERR; |
73 break; | 71 break; |
74 case PAM_PROMPT_ECHO_ON: | 72 } |
75 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_PROMPT_ECHO_ON: (*msg)->msg=\"%s\"", (*msg)->msg); | 73 |
76 | 74 /* XXX leak */ |
77 if ((strcmp((*msg)->msg, "login: " ) == 0) || (strcmp((*msg)->msg, "Please enter username: " ) == 0)) { | 75 resp = (struct pam_response*) m_malloc(sizeof(struct pam_response)); |
78 resp = (struct pam_response*) malloc(sizeof(struct pam_response)); | 76 /* XXX leak */ |
79 resp->resp = (char*) strdup(userDatap->user); | 77 resp->resp = (char*) m_strdup(userDatap->passwd); |
80 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_PROMPT_ECHO_ON: userDatap->user=\"%s\"", userDatap->user); | 78 resp->resp_retcode = 0; |
81 resp->resp_retcode = 0; | 79 (*respp) = resp; |
82 (*respp) = resp; | 80 break; |
83 } | 81 |
84 else { | 82 |
85 dropbear_log(LOG_WARNING, "pamConvFunc(): PAM_PROMPT_ECHO_ON: unrecognized prompt, (*msg)->msg=\"%s\"", | 83 case PAM_PROMPT_ECHO_ON: |
86 (*msg)->msg); | 84 |
87 rc = PAM_CONV_ERR; | 85 if ((strcmp(message, "login: " ) != 0) |
88 } | 86 && (strcmp(message, "login:" ) != 0) |
89 break; | 87 && (strcmp(message, "Please enter username: " ) != 0)) { |
90 case PAM_ERROR_MSG: | 88 TRACE(("PAM_PROMPT_ECHO_ON: unrecognized prompt")); |
91 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_ERROR_MSG: (*msg)->msg=\"%s\"", (*msg)->msg); | 89 rc = PAM_CONV_ERR; |
92 /* printf("error msg: '%s'\n", (*msg)->msg); */ | 90 break; |
93 rc = PAM_CONV_ERR; | 91 } |
94 break; | 92 |
95 case PAM_TEXT_INFO: | 93 /* XXX leak */ |
96 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_TEXT_INFO: (*msg)->msg=\"%s\"", (*msg)->msg); | 94 resp = (struct pam_response*) m_malloc(sizeof(struct pam_response)); |
97 /* printf("text info: '%s'\n", (*msg)->msg); */ | 95 /* XXX leak */ |
98 rc = PAM_CONV_ERR; | 96 resp->resp = (char*) m_strdup(userDatap->user); |
99 break; | 97 TRACE(("userDatap->user='%s'", userDatap->user)); |
100 case PAM_RADIO_TYPE: | 98 |
101 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_RADIO_TYPE: (*msg)->msg=\"%s\"", (*msg)->msg); | 99 resp->resp_retcode = 0; |
102 /* printf("radio type: '%s'\n", (*msg)->msg); */ | 100 (*respp) = resp; |
103 rc = PAM_CONV_ERR; | 101 break; |
104 break; | 102 |
105 case PAM_BINARY_PROMPT: | 103 case PAM_ERROR_MSG: |
106 dropbear_log(LOG_DEBUG, "pamConvFunc(): PAM_BINARY_PROMPT: (*msg)->msg=\"%s\"", (*msg)->msg); | 104 case PAM_TEXT_INFO: |
107 /* printf("binary prompt: '%s'\n", (*msg)->msg); */ | 105 case PAM_RADIO_TYPE: |
108 rc = PAM_CONV_ERR; | 106 case PAM_BINARY_PROMPT: |
109 break; | 107 TRACE(("Unhandled message type")); |
110 default: | 108 rc = PAM_CONV_ERR; |
111 dropbear_log(LOG_DEBUG, "pamConvFunc(): Unknown PAM message"); | 109 break; |
112 /* printf("unknown message\n"); */ | 110 |
113 rc = PAM_CONV_ERR; | 111 default: |
114 break; | 112 TRACE(("Unknown message type")); |
115 } | 113 rc = PAM_CONV_ERR; |
116 | 114 break; |
117 return rc; | 115 } |
116 | |
117 TRACE(("leave pamConvFunc, rc %d", rc)); | |
118 | |
119 return rc; | |
118 } | 120 } |
119 | 121 |
120 /* Process a password auth request, sending success or failure messages as | 122 /* Process a password auth request, sending success or failure messages as |
121 * appropriate */ | 123 * appropriate. To the client it looks like it's doing normal password auth (as opposed to keyboard-interactive or something), so the pam module has to be fairly standard (ie just "what's your username, what's your password, OK"). |
124 * | |
125 * Keyboard interactive would be a lot nicer, but since PAM is synchronous, it | |
126 * gets very messy trying to send the interactive challenges, and read the | |
127 * interactive responses, over the network. */ | |
122 void svr_auth_pam() { | 128 void svr_auth_pam() { |
123 // PAM stuff | 129 |
124 int rc = PAM_SUCCESS; | 130 struct UserDataS userData; |
125 struct UserDataS userData; | 131 struct pam_conv pamConv = { |
126 struct pam_conv pamConv = { | 132 pamConvFunc, |
127 pamConvFunc, | 133 &userData /* submitted to pamvConvFunc as appdata_ptr */ |
128 &userData /* submitted to pamvConvFunc as appdata_ptr */ | 134 }; |
129 }; | 135 |
130 pam_handle_t* pamHandlep = NULL; | 136 pam_handle_t* pamHandlep = NULL; |
131 unsigned char * password = NULL; | 137 |
132 unsigned int passwordlen; | 138 unsigned char * password = NULL; |
133 | 139 unsigned int passwordlen; |
134 unsigned char changepw; | 140 |
135 | 141 int rc = PAM_SUCCESS; |
136 /* check if client wants to change password */ | 142 unsigned char changepw; |
137 changepw = buf_getbyte(ses.payload); | 143 |
138 if (changepw) { | 144 /* check if client wants to change password */ |
139 /* not implemented by this server */ | 145 changepw = buf_getbyte(ses.payload); |
140 send_msg_userauth_failure(0, 1); | 146 if (changepw) { |
141 return; | 147 /* not implemented by this server */ |
142 } | 148 send_msg_userauth_failure(0, 1); |
143 | 149 goto cleanup; |
144 password = buf_getstring(ses.payload, &passwordlen); | 150 } |
145 | 151 |
146 /* clear the buffer containing the password */ | 152 password = buf_getstring(ses.payload, &passwordlen); |
147 buf_incrpos(ses.payload, -passwordlen - 4); | 153 |
148 m_burn(buf_getptr(ses.payload, passwordlen + 4), passwordlen + 4); | 154 /* used to pass data to the PAM conversation function */ |
149 | 155 userData.user = ses.authstate.printableuser; |
150 /* used to pass data to the PAM conversation function */ | 156 userData.passwd = password; |
151 userData.user = ses.authstate.printableuser; | 157 |
152 TRACE(("user is %s\n", userData.user)); | 158 /* Init pam */ |
153 userData.passwd = password; | 159 if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) { |
154 | 160 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s\n", |
155 /* Init pam */ | 161 rc, pam_strerror(pamHandlep, rc)); |
156 if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) { | 162 goto cleanup; |
157 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); | 163 } |
158 /* fprintf(stderr, "pam_start() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); */ | 164 |
159 goto clean; | 165 /* just to set it to something */ |
160 } | 166 if ((rc = pam_set_item(pamHandlep, PAM_TTY, "ssh") != PAM_SUCCESS)) { |
161 | 167 dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s\n", |
162 /* | 168 rc, pam_strerror(pamHandlep, rc)); |
163 if ((rc = pam_set_item(pamHandlep, PAM_RHOST, webReqp->ipaddr) != PAM_SUCCESS)) { | 169 goto cleanup; |
164 dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); | 170 } |
165 return; | 171 |
166 } | 172 (void) pam_fail_delay(pamHandlep, 0 /* musec_delay */); |
167 */ | 173 |
168 | 174 /* (void) pam_set_item(pamHandlep, PAM_FAIL_DELAY, (void*) pamDelayFunc); */ |
169 /* just to set it to something */ | 175 |
170 if ((rc = pam_set_item(pamHandlep, PAM_TTY, "ssh") != PAM_SUCCESS)) { | 176 if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) { |
171 dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); | 177 dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s\n", |
172 goto clean; | 178 rc, pam_strerror(pamHandlep, rc)); |
173 } | 179 dropbear_log(LOG_WARNING, |
174 | 180 "bad pam password attempt for '%s'", |
175 (void) pam_fail_delay(pamHandlep, 0 /* musec_delay */); | 181 ses.authstate.printableuser); |
176 | 182 send_msg_userauth_failure(0, 1); |
177 /* (void) pam_set_item(pamHandlep, PAM_FAIL_DELAY, (void*) pamDelayFunc); */ | 183 goto cleanup; |
178 | 184 } |
179 if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) { | 185 |
180 dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); | 186 if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) { |
181 /* fprintf(stderr, "pam_authenticate() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); */ | 187 dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s\n", |
182 dropbear_log(LOG_WARNING, | 188 rc, pam_strerror(pamHandlep, rc)); |
183 "bad pam password attempt for '%s'", | 189 dropbear_log(LOG_WARNING, |
184 ses.authstate.printableuser); | 190 "bad pam password attempt for '%s'", |
185 send_msg_userauth_failure(0, 1); | 191 ses.authstate.printableuser); |
186 goto clean; | 192 send_msg_userauth_failure(0, 1); |
187 } | 193 goto cleanup; |
188 | 194 } |
189 if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) { | 195 |
190 dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); | 196 /* successful authentication */ |
191 /* fprintf(stderr, "pam_acct_mgmt() failed, rc=%d, %s\n", rc, pam_strerror(pamHandlep, rc)); */ | 197 dropbear_log(LOG_NOTICE, "pam password auth succeeded for '%s'", |
192 dropbear_log(LOG_WARNING, | 198 ses.authstate.printableuser); |
193 "bad pam password attempt for '%s'", | 199 send_msg_userauth_success(); |
194 ses.authstate.printableuser); | 200 |
195 send_msg_userauth_failure(0, 1); | 201 cleanup: |
196 goto clean; | 202 if (password != NULL) { |
197 } | 203 m_burn(password, passwordlen); |
198 | 204 m_free(password); |
199 /* successful authentication */ | 205 } |
200 dropbear_log(LOG_NOTICE, | 206 if (pamHandlep != NULL) { |
201 "password auth succeeded for '%s'", | 207 (void) pam_end(pamHandlep, 0 /* pam_status */); |
202 ses.authstate.printableuser); | 208 } |
203 send_msg_userauth_success(); | |
204 | |
205 clean: | |
206 if (password != NULL) { | |
207 m_burn(password, passwordlen); | |
208 m_free(password); | |
209 } | |
210 if (pamHandlep != NULL) { | |
211 (void) pam_end(pamHandlep, 0 /* pam_status */); | |
212 } | |
213 } | 209 } |
214 | |
215 #endif /* DROPBEAR_PAM_AUTH */ |