that style of mine 2 years ago hurt my eyes
[apps/pfixtools.git] / srsd.c
1 /******************************************************************************/
2 /*          postlicyd: a postfix policy daemon with a lot of features         */
3 /*          ~~~~~~~~~                                                         */
4 /*  ________________________________________________________________________  */
5 /*                                                                            */
6 /*  Redistribution and use in source and binary forms, with or without        */
7 /*  modification, are permitted provided that the following conditions        */
8 /*  are met:                                                                  */
9 /*                                                                            */
10 /*  1. Redistributions of source code must retain the above copyright         */
11 /*     notice, this list of conditions and the following disclaimer.          */
12 /*  2. Redistributions in binary form must reproduce the above copyright      */
13 /*     notice, this list of conditions and the following disclaimer in the    */
14 /*     documentation and/or other materials provided with the distribution.   */
15 /*  3. The names of its contributors may not be used to endorse or promote    */
16 /*     products derived from this software without specific prior written     */
17 /*     permission.                                                            */
18 /*                                                                            */
19 /*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
20 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
21 /*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
22 /*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
23 /*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
24 /*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
25 /*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
26 /*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
27 /*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
28 /*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
29 /*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
30 /******************************************************************************/
31
32 /*
33  * Copyright © 2005-2007 Pierre Habouzit
34  */
35
36 #include <fcntl.h>
37 #include <sys/stat.h>
38
39 #include <srs2.h>
40
41 #include "common.h"
42 #include "mem.h"
43
44 #define MAX_SIZE 0x10000
45
46 static char **read_sfile(char *sfile)
47 {
48     int fd  = -1;
49     int pos = 0;
50     int nb  = 0;
51     int len = 0;
52
53     char  *buf = NULL;
54     char **res = NULL;
55
56     struct stat stat_buf;
57
58     if (stat(sfile, &stat_buf)) {
59         perror("stat");
60         exit(1);
61     }
62
63     if (stat_buf.st_size > MAX_SIZE) {
64         fprintf(stderr, "the secret file is too big\n");
65         exit(1);
66     }
67
68     buf = (char *)malloc(stat_buf.st_size+1);
69     buf[stat_buf.st_size] = 0;
70
71     if ((fd = open(sfile, O_RDONLY)) < 0) {
72         perror("open");
73         exit (1);
74     }
75
76     for (;;) {
77         if ((nb = read(fd, &(buf[pos]), stat_buf.st_size)) < 0) {
78             if (errno == EINTR)
79                 continue;
80             perror("read");
81             exit(1);
82         }
83         pos += nb;
84         if (nb == 0 || pos == stat_buf.st_size) {
85             close(fd);
86             fd = -1;
87             break;
88         }
89     }
90
91     for (nb = pos = 0; pos < stat_buf.st_size ; pos++) {
92         if (buf[pos] == '\n') {
93             nb++;
94             buf[pos] = 0;
95         }
96     }
97
98     res = p_new(char*, nb + 2);
99
100     nb = pos = 0;
101     while (pos < stat_buf.st_size) {
102         len = strlen(&(buf[pos]));
103         if (len) {
104             res[nb++] = &(buf[pos]);
105         }
106         pos += len+1;
107     }
108
109     return res;
110 }
111
112
113 static char *encode(char *secret, char *sender, char *alias)
114 {
115     int    err = 0;
116     char  *res = NULL;
117     srs_t *srs = srs_new();
118
119     srs_add_secret(srs, secret);
120     err = srs_forward_alloc(srs, &res, sender, alias);
121
122     if (res == NULL) {
123         fprintf(stderr, "%s\n", srs_strerror(err));
124         exit (1);
125     }
126
127     return res;
128 }
129
130 static char *decode(char *secret, char *secrets[], char *sender)
131 {
132     int    err = 0;
133     char  *res = NULL;
134     srs_t *srs = srs_new();
135
136     if (secret) {
137         srs_add_secret(srs, secret);
138     }
139
140     for (; secrets && secrets[err] != 0; err++) {
141         srs_add_secret(srs, secrets[err]);
142     }
143
144     err = srs_reverse_alloc(srs, &res, sender);
145
146     if (res == NULL) {
147         fprintf(stderr, "%s\n", srs_strerror(err));
148         exit(1);
149     }
150
151     return res;
152 }
153
154 static void help(void)
155 {
156     puts(
157             "Usage: srs-c [ -r | -d domain ] [ -s secret | -f sfile ] -e sender\n"
158             "Perform an SRS encoding / decoding\n"
159             "\n"
160             "    -r          perform an SRS decoding\n"
161             "    -d domain   use that domain (required for encoding)\n"
162             "\n"
163             "    -s secret   secret used in the encoding (sfile required if omitted)\n"
164             "    -f sfile    secret file for decoding.  the first line is taken if -s omitted\n"
165             "\n"
166             "    -e sender   the sender address we want to encode/decode\n"
167           );
168     exit (1);
169 }
170
171 int main(int argc, char *argv[])
172 {
173     char *buf    = NULL;
174     char *domain = NULL;
175     char *sender = NULL;
176     char *secret = NULL;
177     char *sfile  = NULL;
178
179     int    opt   = 0;
180     bool   rev   = false;
181     char **secr  = NULL;
182
183     while ((opt = getopt(argc, argv, "d:e:s:f:r")) != -1) {
184         switch (opt) {
185             case 'd': domain = optarg;  break;
186             case 'e': sender = optarg;  break;
187             case 'f': sfile  = optarg;  break;
188             case 'r': rev    = true;    break;
189             case 's': secret = optarg;  break;
190         }
191     }
192
193     if (!sender || !(secret||sfile) || !(rev||domain)) {
194         help ();
195     }
196
197     if (sfile) {
198         secr = read_sfile(sfile);
199         if (!secret && (!secr || !secr[0])) {
200             fprintf(stderr, "No secret given, and secret file is empty\n");
201             exit (1);
202         }
203     }
204
205     if (rev) {
206         buf = decode(secret, secr, sender);
207     } else {
208         buf = encode((secret ? secret : secr[0]), sender, domain);
209     }
210
211     puts(buf);
212     return 0;
213 }