[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
CVS gsasl/lib/kerberos_v5
From: |
gsasl-commit |
Subject: |
CVS gsasl/lib/kerberos_v5 |
Date: |
Sat, 18 Sep 2004 18:53:40 +0200 |
Update of /home/cvs/gsasl/lib/kerberos_v5
In directory dopio:/tmp/cvs-serv31663/lib/kerberos_v5
Modified Files:
Makefile.am
Added Files:
client.c server.c shared.h
Log Message:
Split up KERBEROS_V5.
--- /home/cvs/gsasl/lib/kerberos_v5/Makefile.am 2004/06/18 11:22:19 1.9
+++ /home/cvs/gsasl/lib/kerberos_v5/Makefile.am 2004/09/18 16:53:40 1.10
@@ -23,5 +23,13 @@
-I$(srcdir)/../gl
noinst_LTLIBRARIES = libgsasl-kerberos_v5.la
-libgsasl_kerberos_v5_la_SOURCES = kerberos_v5.h kerberos_v5.c
+libgsasl_kerberos_v5_la_SOURCES = kerberos_v5.h shared.h
libgsasl_kerberos_v5_la_LIBADD = $(top_builddir)/gl/libgl.la
+
+if CLIENT
+libgsasl_kerberos_v5_la_SOURCES += client.c
+endif
+
+if SERVER
+libgsasl_kerberos_v5_la_SOURCES += server.c
+endif
--- /home/cvs/gsasl/lib/kerberos_v5/client.c 2004/09/18 16:53:40 NONE
+++ /home/cvs/gsasl/lib/kerberos_v5/client.c 2004/09/18 16:53:40 1.1
/* client.c --- Experimental SASL mechanism KERBEROS_V5, client side.
* Copyright (C) 2003, 2004 Simon Josefsson
*
* This file is part of GNU SASL Library.
*
* GNU SASL Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GNU SASL Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU SASL Library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* NB! Shishi is licensed under GPL, so linking GSASL with it require
* that you follow the GPL for GSASL as well.
*
*/
#include "kerberos_v5.h"
#include "shared.h"
struct _Gsasl_kerberos_v5_client_state
{
int step;
char serverhello[BITMAP_LEN + MAXBUF_LEN + RANDOM_LEN];
int serverqops;
int clientqop;
int servermutual;
uint32_t servermaxbuf;
uint32_t clientmaxbuf;
Shishi *sh;
Shishi_tkt *tkt;
Shishi_as *as;
Shishi_ap *ap;
Shishi_key *sessionkey;
Shishi_safe *safe;
};
int
_gsasl_kerberos_v5_client_init (Gsasl_ctx * ctx)
{
if (!shishi_check_version (SHISHI_VERSION))
return GSASL_UNKNOWN_MECHANISM;
return GSASL_OK;
}
int
_gsasl_kerberos_v5_client_start (Gsasl_session_ctx * sctx, void **mech_data)
{
struct _Gsasl_kerberos_v5_client_state *state;
Gsasl_ctx *ctx;
int err;
state = malloc (sizeof (*state));
if (state == NULL)
return GSASL_MALLOC_ERROR;
memset (state, 0, sizeof (*state));
err = shishi_init (&state->sh);
if (err)
return GSASL_KERBEROS_V5_INIT_ERROR;
state->step = 0;
state->clientqop = GSASL_QOP_AUTH_INT;
*mech_data = state;
return GSASL_OK;
}
#define STEP_FIRST 0
#define STEP_NONINFRA_SEND_ASREQ 1
#define STEP_NONINFRA_WAIT_ASREP 2
#define STEP_NONINFRA_SEND_APREQ 3
#define STEP_NONINFRA_WAIT_APREP 4
#define STEP_SUCCESS 5
int
_gsasl_kerberos_v5_client_step (Gsasl_session_ctx * sctx,
void *mech_data,
const char *input,
size_t input_len,
char *output, size_t * output_len)
{
struct _Gsasl_kerberos_v5_client_state *state = mech_data;
Gsasl_client_callback_authentication_id cb_authentication_id;
Gsasl_client_callback_authorization_id cb_authorization_id;
Gsasl_client_callback_qop cb_qop;
Gsasl_client_callback_realm cb_realm;
Gsasl_client_callback_password cb_password;
Gsasl_client_callback_service cb_service;
Gsasl_client_callback_maxbuf cb_maxbuf;
Gsasl_ctx *ctx;
int res;
int len;
ctx = gsasl_client_ctx_get (sctx);
if (ctx == NULL)
return GSASL_CANNOT_GET_CTX;
/* These are optional */
cb_realm = gsasl_client_callback_realm_get (ctx);
cb_service = gsasl_client_callback_service_get (ctx);
cb_authentication_id = gsasl_client_callback_authentication_id_get (ctx);
cb_authorization_id = gsasl_client_callback_authorization_id_get (ctx);
cb_qop = gsasl_client_callback_qop_get (ctx);
cb_maxbuf = gsasl_client_callback_maxbuf_get (ctx);
/* Only optionally needed in infrastructure mode */
cb_password = gsasl_client_callback_password_get (ctx);
if (cb_password == NULL)
return GSASL_NEED_CLIENT_PASSWORD_CALLBACK;
/* I think we really need this one */
cb_service = gsasl_client_callback_service_get (ctx);
if (cb_service == NULL)
return GSASL_NEED_CLIENT_SERVICE_CALLBACK;
switch (state->step)
{
case STEP_FIRST:
if (input == NULL)
{
*output_len = 0;
return GSASL_NEEDS_MORE;
}
if (input_len != SERVER_HELLO_LEN)
return GSASL_MECHANISM_PARSE_ERROR;
memcpy (state->serverhello, input, input_len);
{
unsigned char serverbitmap;
memcpy (&serverbitmap, input, BITMAP_LEN);
state->serverqops = 0;
if (serverbitmap & GSASL_QOP_AUTH)
state->serverqops |= GSASL_QOP_AUTH;
if (serverbitmap & GSASL_QOP_AUTH_INT)
state->serverqops |= GSASL_QOP_AUTH_INT;
if (serverbitmap & GSASL_QOP_AUTH_CONF)
state->serverqops |= GSASL_QOP_AUTH_CONF;
if (serverbitmap & MUTUAL)
state->servermutual = 1;
}
memcpy (&state->servermaxbuf, &input[BITMAP_LEN], MAXBUF_LEN);
state->servermaxbuf = ntohl (state->servermaxbuf);
if (cb_qop)
state->clientqop = cb_qop (sctx, state->serverqops);
if (!(state->serverqops & state->clientqop &
(GSASL_QOP_AUTH | GSASL_QOP_AUTH_INT | GSASL_QOP_AUTH_CONF)))
return GSASL_AUTHENTICATION_ERROR;
/* XXX for now we require server authentication */
if (!state->servermutual)
return GSASL_AUTHENTICATION_ERROR;
/* Decide policy here: non-infrastructure, infrastructure or proxy.
*
* A callback to decide should be added, but without the default
* should be:
*
* IF shishi_tktset_get_for_server() THEN
* INFRASTRUCTURE MODE
* ELSE IF shishi_realm_for_server(server) THEN
* PROXY INFRASTRUCTURE (then fallback to NIM?)
* ELSE
* NON-INFRASTRUCTURE MODE
*/
state->step = STEP_NONINFRA_SEND_APREQ; /* only NIM for now.. */
/* fall through */
case STEP_NONINFRA_SEND_ASREQ:
res = shishi_as (state->sh, &state->as);
if (res)
return GSASL_KERBEROS_V5_INTERNAL_ERROR;
if (cb_authentication_id) /* Shishi defaults to one otherwise */
{
len = *output_len - 1;
res = cb_authentication_id (sctx, output, &len);
if (res != GSASL_OK)
return res;
output[len] = '\0';
res = shishi_kdcreq_set_cname (state->sh, shishi_as_req (state->as),
SHISHI_NT_UNKNOWN, output);
if (res != GSASL_OK)
return res;
}
if (cb_realm)
{
len = *output_len - 1;
res = cb_realm (sctx, output, &len);
if (res != GSASL_OK)
return res;
}
else
len = 0;
output[len] = '\0';
res = shishi_kdcreq_set_realm (state->sh, shishi_as_req (state->as),
output);
if (res != GSASL_OK)
return res;
if (cb_service)
{
char *sname[3];
size_t servicelen = 0;
size_t hostnamelen = 0;
res = cb_service (sctx, NULL, &servicelen, NULL, &hostnamelen,
/* XXX support servicename a'la DIGEST-MD5 too? */
NULL, NULL);
if (res != GSASL_OK)
return res;
if (*output_len < servicelen + 1 + hostnamelen + 1)
return GSASL_TOO_SMALL_BUFFER;
sname[0] = &output[0];
sname[1] = &output[servicelen + 2];
sname[2] = NULL;
res = cb_service (sctx, sname[0], &servicelen,
sname[1], &hostnamelen, NULL, NULL);
if (res != GSASL_OK)
return res;
sname[0][servicelen] = '\0';
sname[1][hostnamelen] = '\0';
res = shishi_kdcreq_set_sname (state->sh, shishi_as_req (state->as),
SHISHI_NT_UNKNOWN, sname);
if (res != GSASL_OK)
return res;
}
/* XXX query application for encryption types and set the etype
field? Already configured by shishi though... */
res = shishi_a2d (state->sh, shishi_as_req (state->as),
output, output_len);
if (res != SHISHI_OK)
return GSASL_KERBEROS_V5_INTERNAL_ERROR;
state->step = STEP_NONINFRA_WAIT_ASREP;
res = GSASL_NEEDS_MORE;
break;
case STEP_NONINFRA_WAIT_ASREP:
if (shishi_as_rep_der_set (state->as, input, input_len) != SHISHI_OK)
return GSASL_MECHANISM_PARSE_ERROR;
/* XXX? password stored in callee's output buffer */
len = *output_len - 1;
res = cb_password (sctx, output, &len);
if (res != GSASL_OK && res != GSASL_NEEDS_MORE)
return res;
output[len] = '\0';
res = shishi_as_rep_process (state->as, NULL, output);
if (res != SHISHI_OK)
return GSASL_AUTHENTICATION_ERROR;
state->step = STEP_NONINFRA_SEND_APREQ;
/* fall through */
case STEP_NONINFRA_SEND_APREQ:
if (*output_len <= CLIENT_HELLO_LEN + SERVER_HELLO_LEN)
return GSASL_TOO_SMALL_BUFFER;
if (!(state->clientqop & ~GSASL_QOP_AUTH))
state->clientmaxbuf = 0;
else if (cb_maxbuf)
state->clientmaxbuf = cb_maxbuf (sctx, state->servermaxbuf);
else
state->clientmaxbuf = MAXBUF_DEFAULT;
/* XXX for now we require server authentication */
output[0] = state->clientqop | MUTUAL;
{
uint32_t tmp;
tmp = ntohl (state->clientmaxbuf);
memcpy (&output[BITMAP_LEN], &tmp, MAXBUF_LEN);
}
memcpy (&output[CLIENT_HELLO_LEN], state->serverhello,
SERVER_HELLO_LEN);
if (cb_authorization_id)
{
len = *output_len - CLIENT_HELLO_LEN + SERVER_HELLO_LEN;
res = cb_authorization_id (sctx, &output[CLIENT_HELLO_LEN +
SERVER_HELLO_LEN], &len);
}
else
len = 0;
len += CLIENT_HELLO_LEN + SERVER_HELLO_LEN;
res = shishi_ap_tktoptionsdata (state->sh,
&state->ap,
shishi_as_tkt (state->as),
SHISHI_APOPTIONS_MUTUAL_REQUIRED,
output, len);
if (res != SHISHI_OK)
return GSASL_KERBEROS_V5_INTERNAL_ERROR;
res = shishi_authenticator_add_authorizationdata
(state->sh, shishi_ap_authenticator (state->ap), -1, output, len);
if (res != SHISHI_OK)
return GSASL_KERBEROS_V5_INTERNAL_ERROR;
/* XXX set realm in AP-REQ and Authenticator */
res = shishi_ap_req_der (state->ap, output, output_len);
if (res != SHISHI_OK)
return GSASL_KERBEROS_V5_INTERNAL_ERROR;
state->step = STEP_NONINFRA_WAIT_APREP;
res = GSASL_NEEDS_MORE;
break;
case STEP_NONINFRA_WAIT_APREP:
if (shishi_ap_rep_der_set (state->ap, input, input_len) != SHISHI_OK)
return GSASL_MECHANISM_PARSE_ERROR;
res = shishi_ap_rep_verify (state->ap);
if (res != SHISHI_OK)
return GSASL_AUTHENTICATION_ERROR;
state->step = STEP_SUCCESS;
/* XXX support AP session keys */
state->sessionkey = shishi_tkt_key (shishi_as_tkt (state->as));
*output_len = 0;
res = GSASL_OK;
break;
default:
res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
break;
}
return res;
}
int
_gsasl_kerberos_v5_client_encode (Gsasl_session_ctx * sctx,
void *mech_data,
const char *input,
size_t input_len,
char *output, size_t * output_len)
{
struct _Gsasl_kerberos_v5_client_state *state = mech_data;
int res;
if (state && state->sessionkey && state->clientqop & GSASL_QOP_AUTH_CONF)
{
/* XXX */
}
else if (state && state->sessionkey
&& state->clientqop & GSASL_QOP_AUTH_INT)
{
res = shishi_safe (state->sh, &state->safe);
[69 lines skipped]
--- /home/cvs/gsasl/lib/kerberos_v5/server.c 2004/09/18 16:53:40 NONE
+++ /home/cvs/gsasl/lib/kerberos_v5/server.c 2004/09/18 16:53:40 1.1
[668 lines skipped]
--- /home/cvs/gsasl/lib/kerberos_v5/shared.h 2004/09/18 16:53:40 NONE
+++ /home/cvs/gsasl/lib/kerberos_v5/shared.h 2004/09/18 16:53:40 1.1
[713 lines skipped]