lib/misc/md5-crypt.c
author "Tomas Zeman <tzeman@volny.cz>"
Wed, 16 Jan 2008 22:39:43 +0100
changeset 0 6f7a81934006
permissions -rw-r--r--
Imported vmailmgr-0.96.9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     1
/* One way encryption based on MD5 sum.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     2
   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     3
   This file is part of the GNU C Library.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     4
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     5
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     6
   The GNU C Library is free software; you can redistribute it and/or
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     7
   modify it under the terms of the GNU Library General Public License as
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     8
   published by the Free Software Foundation; either version 2 of the
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
     9
   License, or (at your option) any later version.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    10
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    11
   The GNU C Library is distributed in the hope that it will be useful,
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    14
   Library General Public License for more details.
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    15
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    16
   You should have received a copy of the GNU Library General Public
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    17
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    18
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    19
   Boston, MA 02111-1307, USA.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    20
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    21
#include <errno.h>
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    22
#include <stdlib.h>
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    23
#include <string.h>
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    24
#include <sys/param.h>
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    25
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    26
#include "md5.h"
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    27
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    28
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    29
/* Define our magic string to mark salt for MD5 "encryption"
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    30
   replacement.  This is meant to be the same as for other MD5 based
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    31
   encryption implementations.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    32
static const char md5_salt_prefix[] = "$1$";
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    33
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    34
/* Table with characters for base64 transformation.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    35
static const char b64t[64] =
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    36
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    37
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    38
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    39
/* Prototypes for local functions.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    40
extern char *md5_crypt_r __P ((const char *key, const char *salt,
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    41
			       char *buffer, int buflen));
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    42
extern char *md5_crypt __P ((const char *key, const char *salt));
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    43
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    44
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    45
#ifndef MAX
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    46
#define MAX(X,Y) (((X)>(Y))?(X):(Y))
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    47
#endif
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    48
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    49
#ifndef MIN
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    50
#define MIN(X,Y) (((X)>(Y))?(Y):(X))
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    51
#endif
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    52
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    53
/* This entry point is equivalent to the `crypt' function in Unix
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    54
   libcs.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    55
char *
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    56
md5_crypt_r (key, salt, buffer, buflen)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    57
     const char *key;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    58
     const char *salt;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    59
     char *buffer;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    60
     int buflen;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    61
{
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    62
  unsigned char alt_result[16];
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    63
  struct md5_ctx ctx;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    64
  struct md5_ctx alt_ctx;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    65
  size_t salt_len;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    66
  size_t key_len;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    67
  size_t cnt;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    68
  char *cp;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    69
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    70
  /* Find beginning of salt string.  The prefix should normally always
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    71
     be present.  Just in case it is not.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    72
  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    73
    /* Skip salt prefix.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    74
    salt += sizeof (md5_salt_prefix) - 1;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    75
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    76
  salt_len = MIN (strcspn (salt, "$"), 8);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    77
  key_len = strlen (key);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    78
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    79
  /* Prepare for the real work.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    80
  md5_init_ctx (&ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    81
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    82
  /* Add the key string.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    83
  md5_process_bytes (key, key_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    84
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    85
  /* Because the SALT argument need not always have the salt prefix we
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    86
     add it separately.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    87
  md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    88
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    89
  /* The last part is the salt string.  This must be at most 8
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    90
     characters and it ends at the first `$' character (for
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    91
     compatibility which existing solutions).  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    92
  md5_process_bytes (salt, salt_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    93
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    94
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    95
  /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    96
     final result will be added to the first context.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    97
  md5_init_ctx (&alt_ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    98
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
    99
  /* Add key.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   100
  md5_process_bytes (key, key_len, &alt_ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   101
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   102
  /* Add salt.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   103
  md5_process_bytes (salt, salt_len, &alt_ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   104
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   105
  /* Add key again.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   106
  md5_process_bytes (key, key_len, &alt_ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   107
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   108
  /* Now get result of this (16 bytes) and add it to the other
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   109
     context.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   110
  md5_finish_ctx (&alt_ctx, alt_result);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   111
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   112
  /* Add for any character in the key one byte of the alternate sum.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   113
  for (cnt = key_len; cnt > 16; cnt -= 16)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   114
    md5_process_bytes (alt_result, 16, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   115
  md5_process_bytes (alt_result, cnt, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   116
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   117
  /* For the following code we need a NUL byte.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   118
  *alt_result = '\0';
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   119
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   120
  /* The original implementation now does something weird: for every 1
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   121
     bit in the key the first 0 is added to the buffer, for every 0
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   122
     bit the first character of the key.  This does not seem to be
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   123
     what was intended but we have to follow this to be compatible.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   124
  for (cnt = key_len; cnt > 0; cnt >>= 1)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   125
    md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   126
		       &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   127
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   128
  /* Create intermediate result.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   129
  md5_finish_ctx (&ctx, alt_result);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   130
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   131
  /* Now comes another weirdness.  In fear of password crackers here
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   132
     comes a quite long loop which just processes the output of the
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   133
     previous round again.  We cannot ignore this here.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   134
  for (cnt = 0; cnt < 1000; ++cnt)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   135
    {
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   136
      /* New context.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   137
      md5_init_ctx (&ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   138
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   139
      /* Add key or last result.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   140
      if ((cnt & 1) != 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   141
	md5_process_bytes (key, key_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   142
      else
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   143
	md5_process_bytes (alt_result, 16, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   144
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   145
      /* Add salt for numbers not divisible by 3.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   146
      if (cnt % 3 != 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   147
	md5_process_bytes (salt, salt_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   148
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   149
      /* Add key for numbers not divisible by 7.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   150
      if (cnt % 7 != 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   151
	md5_process_bytes (key, key_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   152
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   153
      /* Add key or last result.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   154
      if ((cnt & 1) != 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   155
	md5_process_bytes (alt_result, 16, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   156
      else
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   157
	md5_process_bytes (key, key_len, &ctx);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   158
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   159
      /* Create intermediate result.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   160
      md5_finish_ctx (&ctx, alt_result);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   161
    }
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   162
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   163
  /* Now we can construct the result string.  It consists of three
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   164
     parts.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   165
  strncpy (buffer, md5_salt_prefix, MAX (0, buflen));
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   166
  buflen -= strlen (md5_salt_prefix);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   167
  cp = buffer + strlen (md5_salt_prefix);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   168
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   169
  strncpy (cp, salt, MIN ((size_t) buflen, salt_len));
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   170
  buflen -= MIN ((size_t) buflen, salt_len);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   171
  cp += MIN ((size_t) buflen, salt_len);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   172
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   173
  if (buflen > 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   174
    {
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   175
      *cp++ = '$';
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   176
      --buflen;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   177
    }
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   178
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   179
#define b64_from_24bit(B2, B1, B0, N)					      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   180
  do {									      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   181
    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);			      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   182
    int n = (N);							      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   183
    while (n-- > 0 && buflen > 0)					      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   184
      {									      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   185
	*cp++ = b64t[w & 0x3f];						      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   186
	--buflen;							      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   187
	w >>= 6;							      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   188
      }									      \
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   189
  } while (0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   190
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   191
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   192
  b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   193
  b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   194
  b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   195
  b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   196
  b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   197
  b64_from_24bit (0, 0, alt_result[11], 2);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   198
  if (buflen <= 0)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   199
    {
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   200
      errno = ERANGE;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   201
      buffer = NULL;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   202
    }
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   203
  else
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   204
    *cp = '\0';		/* Terminate the string.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   205
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   206
  /* Clear the buffer for the intermediate result so that people
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   207
     attaching to processes or reading core dumps cannot get any
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   208
     information.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   209
  memset (alt_result, '\0', sizeof (alt_result));
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   210
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   211
  return buffer;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   212
}
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   213
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   214
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   215
char *
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   216
md5_crypt (key, salt)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   217
     const char *key;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   218
     const char *salt;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   219
{
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   220
  /* We don't want to have an arbitrary limit in the size of the
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   221
     password.  We can compute the size of the result in advance and
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   222
     so we can prepare the buffer we pass to `md5_crypt_r'.  */
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   223
  static char *buffer = NULL;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   224
  static int buflen = 0;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   225
  int needed = 3 + strlen (salt) + 1 + 26 + 1;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   226
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   227
  if (buflen < needed)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   228
    {
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   229
      buflen = needed;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   230
      if ((buffer = realloc (buffer, buflen)) == NULL)
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   231
	return NULL;
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   232
    }
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   233
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   234
  return md5_crypt_r (key, salt, buffer, buflen);
6f7a81934006 Imported vmailmgr-0.96.9
"Tomas Zeman <tzeman@volny.cz>"
parents:
diff changeset
   235
}