1 /*
2  * px-crypt.c
3  *		Wrapper for various crypt algorithms.
4  *
5  * Copyright (c) 2001 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *	  notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *	  notice, this list of conditions and the following disclaimer in the
15  *	  documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * contrib/pgcrypto/px-crypt.c
30  */
31 
32 #include "postgres.h"
33 
34 #include "px.h"
35 #include "px-crypt.h"
36 
37 #include "utils/backend_random.h"
38 
39 static char *
run_crypt_des(const char * psw,const char * salt,char * buf,unsigned len)40 run_crypt_des(const char *psw, const char *salt,
41 			  char *buf, unsigned len)
42 {
43 	char	   *res;
44 
45 	res = px_crypt_des(psw, salt);
46 	if (res == NULL || strlen(res) > len - 1)
47 		return NULL;
48 	strcpy(buf, res);
49 	return buf;
50 }
51 
52 static char *
run_crypt_md5(const char * psw,const char * salt,char * buf,unsigned len)53 run_crypt_md5(const char *psw, const char *salt,
54 			  char *buf, unsigned len)
55 {
56 	char	   *res;
57 
58 	res = px_crypt_md5(psw, salt, buf, len);
59 	return res;
60 }
61 
62 static char *
run_crypt_bf(const char * psw,const char * salt,char * buf,unsigned len)63 run_crypt_bf(const char *psw, const char *salt,
64 			 char *buf, unsigned len)
65 {
66 	char	   *res;
67 
68 	res = _crypt_blowfish_rn(psw, salt, buf, len);
69 	return res;
70 }
71 
72 struct px_crypt_algo
73 {
74 	char	   *id;
75 	unsigned	id_len;
76 	char	   *(*crypt) (const char *psw, const char *salt,
77 						  char *buf, unsigned len);
78 };
79 
80 static const struct px_crypt_algo
81 			px_crypt_list[] = {
82 	{"$2a$", 4, run_crypt_bf},
83 	{"$2x$", 4, run_crypt_bf},
84 	{"$2$", 3, NULL},			/* N/A */
85 	{"$1$", 3, run_crypt_md5},
86 	{"_", 1, run_crypt_des},
87 	{"", 0, run_crypt_des},
88 	{NULL, 0, NULL}
89 };
90 
91 char *
px_crypt(const char * psw,const char * salt,char * buf,unsigned len)92 px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
93 {
94 	const struct px_crypt_algo *c;
95 
96 	for (c = px_crypt_list; c->id; c++)
97 	{
98 		if (!c->id_len)
99 			break;
100 		if (strncmp(salt, c->id, c->id_len) == 0)
101 			break;
102 	}
103 
104 	if (c->crypt == NULL)
105 		return NULL;
106 
107 	return c->crypt(psw, salt, buf, len);
108 }
109 
110 /*
111  * salt generators
112  */
113 
114 struct generator
115 {
116 	char	   *name;
117 	char	   *(*gen) (unsigned long count, const char *input, int size,
118 						char *output, int output_size);
119 	int			input_len;
120 	int			def_rounds;
121 	int			min_rounds;
122 	int			max_rounds;
123 };
124 
125 static struct generator gen_list[] = {
126 	{"des", _crypt_gensalt_traditional_rn, 2, 0, 0, 0},
127 	{"md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0},
128 	{"xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF},
129 	{"bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31},
130 	{NULL, NULL, 0, 0, 0, 0}
131 };
132 
133 int
px_gen_salt(const char * salt_type,char * buf,int rounds)134 px_gen_salt(const char *salt_type, char *buf, int rounds)
135 {
136 	struct generator *g;
137 	char	   *p;
138 	char		rbuf[16];
139 
140 	for (g = gen_list; g->name; g++)
141 		if (pg_strcasecmp(g->name, salt_type) == 0)
142 			break;
143 
144 	if (g->name == NULL)
145 		return PXE_UNKNOWN_SALT_ALGO;
146 
147 	if (g->def_rounds)
148 	{
149 		if (rounds == 0)
150 			rounds = g->def_rounds;
151 
152 		if (rounds < g->min_rounds || rounds > g->max_rounds)
153 			return PXE_BAD_SALT_ROUNDS;
154 	}
155 
156 	if (!pg_backend_random(rbuf, g->input_len))
157 		return PXE_NO_RANDOM;
158 
159 	p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
160 	px_memset(rbuf, 0, sizeof(rbuf));
161 
162 	if (p == NULL)
163 		return PXE_BAD_SALT_ROUNDS;
164 
165 	return strlen(p);
166 }
167