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 */