gsasl  1.8.0
challenge.c
Go to the documentation of this file.
00001 /* challenge.c --- Generate a CRAM-MD5 challenge string.
00002  * Copyright (C) 2002-2012 Simon Josefsson
00003  *
00004  * This file is part of GNU SASL Library.
00005  *
00006  * GNU SASL Library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation; either version 2.1 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * GNU SASL Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with GNU SASL Library; if not, write to the Free
00018  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <assert.h>
00026 
00027 /* Get prototype. */
00028 #include "challenge.h"
00029 
00030 /* Get gc_nonce. */
00031 #include <gc.h>
00032 
00033 /*
00034  * From draft-ietf-sasl-crammd5-02.txt:
00035  *
00036  *   The data encoded in the challenge contains a presumptively
00037  *   arbitrary string of random digits, a time-stamp, and the
00038  *   fully-qualified primary host name of the server.
00039  * ...
00040  *   challenge  = "<" 1*DIGIT "." 1*DIGIT "@" hostname ">"
00041  *   hostname   = 1*(ALPHA / DIGIT) *("." / "-" / ALPHA / DIGIT)
00042  *
00043  * This implementation avoid the information leakage by always using 0
00044  * as the time stamp and a fixed host name.  This should be
00045  * unproblematic, as any client that try to validate the challenge
00046  * string somehow, would violate the same specification:
00047  *
00048  *   The client MUST NOT interpret or attempt to validate the
00049  *   contents of the challenge in any way.
00050  *
00051  */
00052 
00053 /* The sequence of X in TEMPLATE must be twice as long as NONCELEN. */
00054 #define NONCELEN 10
00055 #define TEMPLATE "<XXXXXXXXXXXXXXXXXXXX.0@localhost>"
00056 
00057 /* The probabilities for each digit are skewed (0-5 is more likely to
00058    occur than 6-9), but it is just used as a nonce anyway. */
00059 #define DIGIT(c) (((c) & 0x0F) > 9 ?            \
00060                     '0' + ((c) & 0x0F) - 10 :   \
00061                     '0' + ((c) & 0x0F))
00062 
00063 int
00064 cram_md5_challenge (char challenge[CRAM_MD5_CHALLENGE_LEN])
00065 {
00066   char nonce[NONCELEN];
00067   size_t i;
00068   int rc;
00069 
00070   assert (strlen (TEMPLATE) == CRAM_MD5_CHALLENGE_LEN - 1);
00071 
00072   memcpy (challenge, TEMPLATE, CRAM_MD5_CHALLENGE_LEN);
00073 
00074   rc = gc_nonce (nonce, sizeof (nonce));
00075   if (rc != GC_OK)
00076     return -1;
00077 
00078   for (i = 0; i < sizeof (nonce); i++)
00079     {
00080       challenge[1 + i] = DIGIT (nonce[i]);
00081       challenge[11 + i] = DIGIT (nonce[i] >> 4);
00082     }
00083 
00084   return 0;
00085 }