gsasl-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CVS gsasl/lib/digest-md5


From: gsasl-commit
Subject: CVS gsasl/lib/digest-md5
Date: Sat, 18 Sep 2004 18:50:46 +0200

Update of /home/cvs/gsasl/lib/digest-md5
In directory dopio:/tmp/cvs-serv31606/lib/digest-md5

Modified Files:
        Makefile.am 
Added Files:
        client.c getsubopt.c server.c shared.c shared.h 
Removed Files:
        digest-md5.c 
Log Message:
Split up DIGEST-MD5.


--- /home/cvs/gsasl/lib/digest-md5/Makefile.am  2004/04/16 11:16:39     1.8
+++ /home/cvs/gsasl/lib/digest-md5/Makefile.am  2004/09/18 16:50:46     1.9
@@ -23,5 +23,13 @@
        -I$(srcdir)/../gl -I../crypto
 
 noinst_LTLIBRARIES = libgsasl-digest_md5.la
-libgsasl_digest_md5_la_SOURCES = digest-md5.h digest-md5.c
+libgsasl_digest_md5_la_SOURCES = digest-md5.h shared.h shared.c getsubopt.c
 libgsasl_digest_md5_la_LIBADD = $(top_builddir)/gl/libgl.la
+
+if CLIENT
+libgsasl_digest_md5_la_SOURCES += client.c
+endif
+
+if SERVER
+libgsasl_digest_md5_la_SOURCES += server.c
+endif

--- /home/cvs/gsasl/lib/digest-md5/client.c     2004/09/18 16:50:46     NONE
+++ /home/cvs/gsasl/lib/digest-md5/client.c     2004/09/18 16:50:46     1.1
/* client.c --- DIGEST-MD5 mechanism from RFC 2831, client side.
 * Copyright (C) 2002, 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
 *
 */

#include "digest-md5.h"

#include "shared.h"

struct _Gsasl_digest_md5_client_state
{
  int step;
  char secret[MD5LEN];
  char *nonce;
  uint32_t nc;
  char cnonce[2 * CNONCE_ENTROPY_BITS / 8 + 1];
  Gsasl_qop qop;
  Gsasl_cipher cipher;
  char *authzid;
  char *digesturi;
  char response[RESPONSE_LENGTH + 1];
  uint32_t readseqnum, sendseqnum;
  char kic[MD5LEN];
  char kcc[MD5LEN];
  char kis[MD5LEN];
  char kcs[MD5LEN];
};
typedef struct _Gsasl_digest_md5_client_state _Gsasl_digest_md5_client_state;

int
_gsasl_digest_md5_client_start (Gsasl_session_ctx * sctx, void **mech_data)
{
  _Gsasl_digest_md5_client_state *state;
  Gsasl_ctx *ctx;

  ctx = gsasl_client_ctx_get (sctx);
  if (ctx == NULL)
    return GSASL_CANNOT_GET_CTX;

  if (gsasl_client_callback_authentication_id_get (ctx) == NULL)
    return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK;

  if (gsasl_client_callback_password_get (ctx) == NULL)
    return GSASL_NEED_CLIENT_PASSWORD_CALLBACK;

  state = (_Gsasl_digest_md5_client_state *) malloc (sizeof (*state));
  if (state == NULL)
    return GSASL_MALLOC_ERROR;

  state->step = 0;
  state->nonce = NULL;
  state->nc = 1;
  state->cipher = 0;
  state->qop = GSASL_QOP_AUTH;
  state->authzid = NULL;
  state->digesturi = NULL;
  state->readseqnum = 0;
  state->sendseqnum = 0;

  *mech_data = state;

  return GSASL_OK;
}

int
_gsasl_digest_md5_client_step (Gsasl_session_ctx * sctx,
                               void *mech_data,
                               const char *input,
                               size_t input_len,
                               char *output, size_t * output_len)
{
  _Gsasl_digest_md5_client_state *state = mech_data;
  Gsasl_client_callback_authorization_id cb_authorization_id;
  Gsasl_client_callback_authentication_id cb_authentication_id;
  Gsasl_client_callback_password cb_password;
  Gsasl_client_callback_service cb_service;
  Gsasl_client_callback_qop cb_qop;
  Gsasl_client_callback_maxbuf cb_maxbuf;
  char *subopts;
  char *value;
  Gsasl_ctx *ctx;
  int outlen;
  int res, i;

  ctx = gsasl_client_ctx_get (sctx);
  if (ctx == NULL)
    return GSASL_CANNOT_GET_CTX;

  cb_qop = gsasl_client_callback_qop_get (ctx);
  cb_authorization_id = gsasl_client_callback_authorization_id_get (ctx);
  cb_maxbuf = gsasl_client_callback_maxbuf_get (ctx);

  cb_authentication_id = gsasl_client_callback_authentication_id_get (ctx);
  if (cb_authentication_id == NULL)
    return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK;

  cb_password = gsasl_client_callback_password_get (ctx);
  if (cb_password == NULL)
    return GSASL_NEED_CLIENT_PASSWORD_CALLBACK;

  cb_service = gsasl_client_callback_service_get (ctx);
  if (cb_service == NULL)
    return GSASL_NEED_CLIENT_SERVICE_CALLBACK;

  if (*output_len < 1)
    return GSASL_TOO_SMALL_BUFFER;

  strcpy (output, "");
  outlen = 0;

#if CLIENT_PRINT_OUTPUT
  if (input && input_len > 0)
    fprintf (stderr, "%s\n", input);
#endif

  switch (state->step)
    {
    case 0:
      state->step++;
      if (input_len == 0)
        {
          *output_len = 0;
          return GSASL_NEEDS_MORE;
        }
      /* fall through */

    case 1:
      {
        char **realm = NULL;
        size_t nrealm = 0;
        long maxbuf = -1;
        char *zinput = NULL;

        if (input == NULL || input_len == 0)
          return GSASL_MECHANISM_PARSE_ERROR;

        zinput = malloc (input_len + 1);
        if (zinput == NULL)
          return GSASL_MALLOC_ERROR;
        memcpy (zinput, input, input_len);
        zinput[input_len] = '\0';

        gsasl_nonce (state->cnonce, CNONCE_ENTROPY_BITS / 8);
        for (i = 0; i < CNONCE_ENTROPY_BITS / 8; i++)
          {
            state->cnonce[CNONCE_ENTROPY_BITS / 8 + i] =
              HEXCHAR (state->cnonce[i]);
            state->cnonce[i] = HEXCHAR (state->cnonce[i] >> 4);
          }
        state->cnonce[2 * CNONCE_ENTROPY_BITS / 8] = '\0';

        subopts = zinput;
        while (*subopts != '\0')
          switch (_gsasl_getsubopt (&subopts, digest_challenge_opts, &value))
            {
            case CHALLENGE_REALM:
              if (nrealm == 0)
                realm = (char **) malloc (sizeof (*realm));
              else
                realm = realloc (realm, (nrealm + 1) * sizeof (*realm));
              if (realm == NULL)
                {
                  res = GSASL_MALLOC_ERROR;
                  goto done;
                }
              realm[nrealm] = strdup (value);
              nrealm++;
              break;

            case CHALLENGE_NONCE:
              if (state->nonce != NULL)
                {
                  res = GSASL_MECHANISM_PARSE_ERROR;
                  goto done;
                }
              state->nonce = strdup (value);
              break;

            case CHALLENGE_QOP:
              {
                char *subsubopts;
                char *val;

                state->qop = 0;
                subsubopts = value;
                while (*subsubopts != '\0')
                  switch (_gsasl_getsubopt (&subsubopts, qop_opts, &val))
                    {
                    case QOP_AUTH_OPTION:
                      state->qop |= GSASL_QOP_AUTH;
                      break;

                    case QOP_AUTH_INT_OPTION:
                      state->qop |= GSASL_QOP_AUTH_INT;
                      break;

                    case QOP_AUTH_CONF_OPTION:
                      state->qop |= GSASL_QOP_AUTH_CONF;
                      break;

                    default:
                      /* Ignore unknown qop */
                      break;
                    }
              }
              break;

            case CHALLENGE_STALE:
              printf ("XXX stale: %s\n", value);
              break;

            case CHALLENGE_MAXBUF:
              /* draft-ietf-sasl-rfc2831bis-02.txt:
               * server_maxbuf ("maximal ciphertext buffer size")
               * A number indicating the size of the largest buffer
               * the server is able to receive when using "auth-int"
               * or "auth-conf". The value MUST be bigger than 16 and
               * smaller or equal to 16777215 (i.e.  2**24-1). If this
               * directive is missing, the default value is
               * 65536. This directive may appear at most once; if
               * multiple instances are present, the client MUST abort
               * the authentication exchange.
               */
              if (maxbuf != -1)
                {
                  res = GSASL_MECHANISM_PARSE_ERROR;
                  goto done;
                }
              maxbuf = strtol (value, NULL, 10);
              if (maxbuf < MAXBUF_MIN || maxbuf > MAXBUF_MAX)
                {
                  res = GSASL_MECHANISM_PARSE_ERROR;
                  goto done;
                }
              break;

            case CHALLENGE_CHARSET:
              if (strcmp (DEFAULT_CHARSET, value) != 0)
                {
                  res = GSASL_MECHANISM_PARSE_ERROR;
                  goto done;
                }
              break;

            case CHALLENGE_ALGORITHM:
              if (strcmp (DEFAULT_ALGORITHM, value) != 0)
                {
                  res = GSASL_MECHANISM_PARSE_ERROR;
                  goto done;
                }
              break;

            case CHALLENGE_CIPHER:
              {
                char *subsubopts;
                char *val;

                if (state->cipher)
                  {
                    res = GSASL_MECHANISM_PARSE_ERROR;
                    goto done;
                  }

                subsubopts = value;
                while (*subsubopts != '\0')
                  switch (_gsasl_getsubopt (&subsubopts, cipher_opts, &val))
                    {
                    case CIPHER_DES_OPTION:
                      state->cipher |= GSASL_CIPHER_DES;
                      break;

                    case CIPHER_3DES_OPTION:
                      state->cipher |= GSASL_CIPHER_3DES;
                      break;

                    case CIPHER_RC4_OPTION:
                      state->cipher |= GSASL_CIPHER_RC4;
                      break;

                    case CIPHER_RC4_40_OPTION:
                      state->cipher |= GSASL_CIPHER_RC4_40;
                      break;

                    case CIPHER_RC4_56_OPTION:
                      state->cipher |= GSASL_CIPHER_RC4_56;
                      break;

                    case CIPHER_AES_OPTION:
                      state->cipher |= GSASL_CIPHER_AES;
                      break;

                    default:
                      /* Ignoring unknown cipher. */
                      break;
                    }
              }
              break;

            default:
              /* Ignoring unknown parameter. */
              break;
            }
        if (state->qop == 0 || state->nonce == NULL ||
            (state->qop & GSASL_QOP_AUTH_CONF &&
             !(state->cipher & GSASL_CIPHER_3DES)))
          {
            res = GSASL_MECHANISM_PARSE_ERROR;
            goto done;
          }

        if (cb_qop)
          state->qop = cb_qop (sctx, state->qop);
        else
          state->qop = GSASL_QOP_AUTH;

        if (maxbuf == -1)
          maxbuf = MAXBUF_DEFAULT;

        if (cb_authorization_id)
          {
            size_t authzidlen;

            res = cb_authorization_id (sctx, NULL, &authzidlen);
            if (res != GSASL_OK)
              goto done;
            state->authzid = (char *) malloc (authzidlen + 1);
            if (state->authzid == NULL)
              {
                res = GSASL_MALLOC_ERROR;
                goto done;
              }
            res = cb_authorization_id (sctx, state->authzid, &authzidlen);
            if (res != GSASL_OK)
              goto done;
            state->authzid[authzidlen] = '\0';
          }
        /* username */
        {
          size_t usernamelen;

          res = cb_authentication_id (sctx, NULL, &usernamelen);
          if (res != GSASL_OK)
            goto done;

          if (outlen +
              strlen (USERNAME_PRE) +
              usernamelen + strlen (USERNAME_POST) >= *output_len)
            {
              res = GSASL_TOO_SMALL_BUFFER;
              goto done;
            }

          strcat (output, USERNAME_PRE);
          outlen += strlen (USERNAME_PRE);

          res = cb_authentication_id (sctx, &output[outlen], &usernamelen);
          if (res != GSASL_OK)
            goto done;
          outlen += usernamelen;

          strcat (output, USERNAME_POST);
          outlen += strlen (USERNAME_POST);
        }
        /* realm */
        if (nrealm > 0)
          {
            if (outlen +
                strlen (REALM_PRE) +
                strlen (realm[0]) + strlen (REALM_POST) >= *output_len)
              {
                res = GSASL_TOO_SMALL_BUFFER;
                goto done;
              }

            strcat (output, REALM_PRE);
            outlen += strlen (REALM_PRE);

            strcat (output, realm[0]);
            outlen += strlen (realm[0]);

            strcat (output, REALM_POST);
            outlen += strlen (REALM_POST);
          }

[550 lines skipped]
--- /home/cvs/gsasl/lib/digest-md5/getsubopt.c  2004/09/18 16:50:46     NONE
+++ /home/cvs/gsasl/lib/digest-md5/getsubopt.c  2004/09/18 16:50:46     1.1

[658 lines skipped]
--- /home/cvs/gsasl/lib/digest-md5/server.c     2004/09/18 16:50:46     NONE
+++ /home/cvs/gsasl/lib/digest-md5/server.c     2004/09/18 16:50:46     1.1

[1549 lines skipped]
--- /home/cvs/gsasl/lib/digest-md5/shared.c     2004/09/18 16:50:46     NONE
+++ /home/cvs/gsasl/lib/digest-md5/shared.c     2004/09/18 16:50:46     1.1

[1897 lines skipped]
--- /home/cvs/gsasl/lib/digest-md5/shared.h     2004/09/18 16:50:46     NONE
+++ /home/cvs/gsasl/lib/digest-md5/shared.h     2004/09/18 16:50:46     1.1

[2107 lines skipped]




reply via email to

[Prev in Thread] Current Thread [Next in Thread]