1 /* login.c implementation of non-standard SASL mechanism LOGIN
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of libgsasl.
6 * Libgsasl is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libgsasl is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with libgsasl; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 _gsasl_login_client_init (Gsasl_ctx
*ctx
)
33 _gsasl_login_client_done (Gsasl_ctx
*ctx
)
39 _gsasl_login_client_start (Gsasl_session_ctx
*cctx
,
45 ctx
= gsasl_client_ctx_get (cctx
);
47 return GSASL_CANNOT_GET_CTX
;
49 if (gsasl_client_callback_authentication_id_get (ctx
) == NULL
)
50 return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK
;
52 if (gsasl_client_callback_password_get (ctx
) == NULL
)
53 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK
;
55 step
= (int*) malloc(sizeof(*step
));
57 return GSASL_MALLOC_ERROR
;
67 _gsasl_login_client_step (Gsasl_session_ctx
*cctx
,
74 int *step
= mech_data
;
75 Gsasl_client_callback_authentication_id cb_authentication_id
;
76 Gsasl_client_callback_password cb_password
;
81 ctx
= gsasl_client_ctx_get (cctx
);
83 return GSASL_CANNOT_GET_CTX
;
85 cb_authentication_id
= gsasl_client_callback_authentication_id_get (ctx
);
86 if (cb_authentication_id
== NULL
)
87 return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK
;
89 cb_password
= gsasl_client_callback_password_get (ctx
);
90 if (cb_password
== NULL
)
91 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK
;
99 return GSASL_NEEDS_MORE
;
101 res
= cb_authentication_id (cctx
, output
, output_len
);
104 tmp
= gsasl_utf8_nfkc_normalize (output
, *output_len
);
106 return GSASL_UNICODE_NORMALIZATION_ERROR
;
107 if (*output_len
< strlen(tmp
))
108 return GSASL_TOO_SMALL_BUFFER
;
109 memcpy(output
, tmp
, strlen(tmp
));
110 *output_len
+= strlen(tmp
);
113 res
= GSASL_NEEDS_MORE
;
117 res
= cb_password (cctx
, output
, output_len
);
120 tmp
= gsasl_utf8_nfkc_normalize (output
, *output_len
);
122 return GSASL_UNICODE_NORMALIZATION_ERROR
;
123 if (*output_len
< strlen(tmp
))
124 return GSASL_TOO_SMALL_BUFFER
;
125 memcpy(output
, tmp
, strlen(tmp
));
126 *output_len
+= strlen(tmp
);
129 res
= GSASL_NEEDS_MORE
;
138 res
= GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
;
146 _gsasl_login_client_finish (Gsasl_session_ctx
*cctx
,
149 int *step
= mech_data
;
158 struct _Gsasl_login_state
{
162 typedef struct _Gsasl_login_state _Gsasl_login_state
;
164 #define CHALLENGE_USERNAME "User Name"
165 #define CHALLENGE_PASSWORD "Password"
168 _gsasl_login_server_init (Gsasl_ctx
*ctx
)
174 _gsasl_login_server_done (Gsasl_ctx
*ctx
)
180 _gsasl_login_server_start (Gsasl_session_ctx
*sctx
,
183 _Gsasl_login_state
*state
;
186 ctx
= gsasl_server_ctx_get (sctx
);
188 return GSASL_CANNOT_GET_CTX
;
190 if (gsasl_server_callback_validate_get (ctx
) == NULL
&&
191 gsasl_server_callback_retrieve_get (ctx
) == NULL
)
192 return GSASL_NEED_SERVER_VALIDATE_CALLBACK
;
194 state
= (_Gsasl_login_state
*) malloc(sizeof(*state
));
196 return GSASL_MALLOC_ERROR
;
199 state
->username
= NULL
;
207 _gsasl_login_server_step (Gsasl_session_ctx
*sctx
,
214 _Gsasl_login_state
*state
= mech_data
;
215 Gsasl_server_callback_validate cb_validate
;
216 Gsasl_server_callback_retrieve cb_retrieve
;
221 ctx
= gsasl_server_ctx_get (sctx
);
223 return GSASL_CANNOT_GET_CTX
;
225 cb_validate
= gsasl_server_callback_validate_get (ctx
);
226 cb_retrieve
= gsasl_server_callback_retrieve_get (ctx
);
227 if (cb_validate
== NULL
&& cb_retrieve
== NULL
)
228 return GSASL_NEED_SERVER_VALIDATE_CALLBACK
;
233 if (*output_len
< strlen(CHALLENGE_USERNAME
))
234 return GSASL_TOO_SMALL_BUFFER
;
236 memcpy(output
, CHALLENGE_USERNAME
, strlen(CHALLENGE_USERNAME
));
237 *output_len
= strlen(CHALLENGE_USERNAME
);
240 res
= GSASL_NEEDS_MORE
;
245 return GSASL_MECHANISM_PARSE_ERROR
;
247 if (*output_len
< strlen(CHALLENGE_PASSWORD
))
248 return GSASL_TOO_SMALL_BUFFER
;
250 state
->username
= malloc(input_len
+ 1);
251 if (state
->username
== NULL
)
252 return GSASL_MALLOC_ERROR
;
254 memcpy(state
->username
, input
, input_len
);
255 state
->username
[input_len
] = '\0';
257 memcpy(output
, CHALLENGE_PASSWORD
, strlen(CHALLENGE_PASSWORD
));
258 *output_len
= strlen(CHALLENGE_PASSWORD
);
261 res
= GSASL_NEEDS_MORE
;
266 return GSASL_MECHANISM_PARSE_ERROR
;
268 password
= malloc(input_len
+ 1);
269 if (password
== NULL
)
270 return GSASL_MALLOC_ERROR
;
272 memcpy(password
, input
, input_len
);
273 password
[input_len
] = '\0';
277 res
= cb_validate(sctx
, state
->username
, NULL
, password
);
285 res
= cb_retrieve(sctx
, state
->username
, NULL
, NULL
, NULL
, &keylen
);
288 key
= malloc(keylen
);
290 return GSASL_MALLOC_ERROR
;
291 res
= cb_retrieve(sctx
, state
->username
, NULL
, NULL
, key
, &keylen
);
297 normkey
= gsasl_utf8_nfkc_normalize (key
, keylen
);
300 return GSASL_UNICODE_NORMALIZATION_ERROR
;
301 if (strlen(password
) == strlen(normkey
) &&
302 memcmp(normkey
, password
, strlen(normkey
)) == 0)
305 res
= GSASL_AUTHENTICATION_ERROR
;
315 res
= GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
;
323 _gsasl_login_server_finish (Gsasl_session_ctx
*sctx
,
326 _Gsasl_login_state
*state
= mech_data
;
329 free(state
->username
);
335 #endif /* USE_LOGIN */