00001 /* challenge.c --- Generate a CRAM-MD5 challenge string. 00002 * Copyright (C) 2002, 2003, 2004 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 <stddef.h> 00024 #include <stdio.h> 00025 #include <string.h> 00026 #include <assert.h> 00027 00028 /* Get prototype. */ 00029 #include "challenge.h" 00030 00031 /* Get gc_nonce. */ 00032 #include <gc.h> 00033 00034 /* 00035 * From draft-ietf-sasl-crammd5-02.txt: 00036 * 00037 * The data encoded in the challenge contains a presumptively 00038 * arbitrary string of random digits, a time-stamp, and the 00039 * fully-qualified primary host name of the server. 00040 * ... 00041 * challenge = "<" 1*DIGIT "." 1*DIGIT "@" hostname ">" 00042 * hostname = 1*(ALPHA / DIGIT) *("." / "-" / ALPHA / DIGIT) 00043 * 00044 * This implementation avoid the information leakage by always using 0 00045 * as the time stamp and a fixed host name. This should be 00046 * unproblematic, as any client that try to validate the challenge 00047 * string somehow, would violate the same specification: 00048 * 00049 * The client MUST NOT interpret or attempt to validate the 00050 * contents of the challenge in any way. 00051 * 00052 */ 00053 00054 /* The sequence of X in TEMPLATE must be twice as long as NONCELEN. */ 00055 #define NONCELEN 10 00056 #define TEMPLATE "<XXXXXXXXXXXXXXXXXXXX.0@localhost>" 00057 00058 /* The probabilities for each digit are skewed (0-5 is more likely to 00059 occur than 6-9), but it is just used as a nonce anyway. */ 00060 #define DIGIT(c) (((c) & 0x0F) > 9 ? \ 00061 '0' + ((c) & 0x0F) - 10 : \ 00062 '0' + ((c) & 0x0F)) 00063 00064 void 00065 cram_md5_challenge (char challenge[CRAM_MD5_CHALLENGE_LEN]) 00066 { 00067 char nonce[NONCELEN]; 00068 size_t i; 00069 00070 assert (strlen (TEMPLATE) == CRAM_MD5_CHALLENGE_LEN - 1); 00071 00072 memcpy (challenge, TEMPLATE, CRAM_MD5_CHALLENGE_LEN); 00073 00074 gc_nonce (nonce, sizeof (nonce)); 00075 00076 for (i = 0; i < sizeof (nonce); i++) 00077 { 00078 challenge[1 + i] = DIGIT (nonce[i]); 00079 challenge[11 + i] = DIGIT (nonce[i] >> 4); 00080 } 00081 }