~ubuntu-branches/ubuntu/hardy/openswan/hardy-updates

« back to all changes in this revision

Viewing changes to programs/algoinfo/algoinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2005-01-27 16:10:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050127161011-idgybmyz3vwhpfiq
Tags: 2.3.0-2
Urgency HIGH due to security issue and problems with build-deps in sarge.
* Fix the security issue. Please see
  http://www.idefense.com/application/poi/display?id=190&
      type=vulnerabilities&flashstatus=false
  for more details. Thanks to Martin Schulze for informing me about
  this issue.
  Closes: #292458: Openswan XAUTH/PAM Buffer Overflow Vulnerability
* Added a Build-Dependency to lynx.
  Closes: #291143: openswan: FTBFS: Missing build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Program to list all the available algorithms.
 
3
 * 
 
4
 * Copyright (C) 2004   Michael Richardson <mcr@xelerance.com>
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2 of the License, or (at your
 
9
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 
10
 * 
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * for more details.
 
15
 */
 
16
 
 
17
char spi_c_version[] = "RCSID $Id: algoinfo.c,v 1.1 2004/04/29 04:13:02 mcr Exp $";
 
18
 
 
19
#include <asm/types.h>
 
20
#include <sys/types.h>
 
21
#include <sys/ioctl.h>
 
22
/* #include <linux/netdevice.h> */
 
23
#include <net/if.h>
 
24
/* #include <linux/types.h> */ /* new */
 
25
#include <sys/stat.h>
 
26
#include <fcntl.h>
 
27
#include <string.h>
 
28
#include <errno.h>
 
29
 
 
30
/* #include <sys/socket.h> */
 
31
 
 
32
#include <netinet/in.h>
 
33
#include <arpa/inet.h>
 
34
/* #include <linux/ip.h> */
 
35
#include <netdb.h>
 
36
 
 
37
#include <unistd.h>
 
38
#include <getopt.h>
 
39
#include <ctype.h>
 
40
#include <stdio.h>
 
41
#include <stdlib.h>
 
42
#include <openswan.h>
 
43
#if 0
 
44
#include <linux/autoconf.h>    /* CONFIG_IPSEC_PFKEYv2 */
 
45
#endif
 
46
     #include <signal.h>
 
47
     #include <sys/socket.h>
 
48
     #include <pfkeyv2.h>
 
49
     #include <pfkey.h>
 
50
 
 
51
#include "openswan/radij.h"
 
52
#include "openswan/ipsec_encap.h"
 
53
#include "openswan/ipsec_xform.h"
 
54
#include "openswan/ipsec_ipe4.h"
 
55
#include "openswan/ipsec_ah.h"
 
56
#include "openswan/ipsec_esp.h"
 
57
#include "openswan/ipsec_sa.h"  /* IPSEC_SAREF_NULL */
 
58
 
 
59
#include "alg_info.h"
 
60
#include "kernel_alg.h"
 
61
 
 
62
struct encap_msghdr *em;
 
63
 
 
64
/*      
 
65
 *      Manual conn support for ipsec_alg (modular algos).
 
66
 *      Rather ugly to include from pluto dir but avoids
 
67
 *      code duplication.
 
68
 */
 
69
char *program_name;
 
70
int debug = 0;
 
71
int saref = 0;
 
72
char *command;
 
73
extern char *optarg;
 
74
extern int optind, opterr, optopt;
 
75
char scratch[2];
 
76
char *iv = NULL, *enckey = NULL, *authkey = NULL;
 
77
size_t ivlen = 0, enckeylen = 0, authkeylen = 0;
 
78
ip_address edst, dst, src;
 
79
int address_family = 0;
 
80
unsigned char proto = 0;
 
81
int alg = 0;
 
82
 
 
83
#ifdef KERNEL_ALG
 
84
/* 
 
85
 *      Manual connection support for modular algos (ipsec_alg) --Juanjo.
 
86
 */
 
87
#define XF_OTHER_ALG (XF_CLR-1) /* define magic XF_ symbol for alg_info's */
 
88
#include <assert.h>
 
89
const char *alg_string = NULL;  /* algorithm string */
 
90
struct alg_info_esp *alg_info = NULL;   /* algorithm info got from string */
 
91
struct esp_info *esp_info = NULL;       /* esp info from 1st (only) element */
 
92
const char *alg_err;            /* auxiliar for parsing errors */
 
93
int proc_read_ok = 0;           /* /proc/net/pf_key_support read ok */
 
94
#endif /* KERNEL_ALG */
 
95
 
 
96
int replay_window = 0;
 
97
char sa[SATOT_BUF];
 
98
 
 
99
extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */
 
100
int pfkey_sock;
 
101
fd_set pfkey_socks;
 
102
uint32_t pfkey_seq = 0;
 
103
enum life_severity {
 
104
        life_soft = 0,
 
105
        life_hard = 1,
 
106
        life_maxsever = 2
 
107
};
 
108
enum life_type {
 
109
        life_alloc = 0,
 
110
        life_bytes = 1,
 
111
        life_addtime = 2,
 
112
        life_usetime = 3,
 
113
        life_packets = 4,
 
114
        life_maxtype = 5
 
115
};
 
116
 
 
117
#define streql(_a,_b) (!strcmp((_a),(_b)))
 
118
 
 
119
static const char *usage_string = "\
 
120
Usage:\n\
 
121
        in the following, <SA> is: --af <inet | inet6> --edst <dstaddr> --spi <spi> --proto <proto>\n\
 
122
                               OR: --said <proto><.|:><spi>@<dstaddr>\n\
 
123
                          <life> is: --life <soft|hard>-<allocations|bytes|addtime|usetime|packets>=<value>[,...]\n\
 
124
spi --clear\n\
 
125
spi --help\n\
 
126
spi --version\n\
 
127
spi\n\
 
128
spi --del <SA>\n\
 
129
spi --ip4 <SA> --src <encap-src> --dst <encap-dst>\n\
 
130
spi --ip6 <SA> --src <encap-src> --dst <encap-dst>\n\
 
131
spi --ah <algo> <SA> [<life> ][ --replay_window <replay_window> ] --authkey <key>\n\
 
132
        where <algo> is one of: hmac-md5-96 | hmac-sha1-96 | something-loaded \n\
 
133
spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey> --authkey <akey>\n\
 
134
        where <algo> is one of: 3des-md5-96 | 3des-sha1-96\n | something-loaded\
 
135
spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey>\n\
 
136
        where <algo> is:        3des\n\
 
137
spi --comp <algo> <SA>\n\
 
138
        where <algo> is:        deflate\n\
 
139
[ --debug ] is optional to any spi command.\n\
 
140
[ --label <label> ] is optional to any spi command.\n\
 
141
[ --listenreply ]   is optional, and causes the command to stick\n\
 
142
                    around and listen to what the PF_KEY socket says.\n\
 
143
";
 
144
 
 
145
 
 
146
static void
 
147
usage(char *s, FILE *f)
 
148
{
 
149
        /* s argument is actually ignored, at present */
 
150
        fprintf(f, "%s:%s", s, usage_string);
 
151
        exit(-1);
 
152
}
 
153
 
 
154
int
 
155
parse_life_options(uint32_t life[life_maxsever][life_maxtype],
 
156
                   char *life_opt[life_maxsever][life_maxtype],
 
157
                   char *optarg)
 
158
{
 
159
        char *optargp = optarg;
 
160
        char *endptr;
 
161
        
 
162
        do {
 
163
                int life_severity, life_type;
 
164
                char *optargt = optargp;
 
165
                
 
166
                if(strncmp(optargp, "soft", sizeof("soft")-1) == 0) {
 
167
                        life_severity = life_soft;
 
168
                        optargp += sizeof("soft")-1;
 
169
                } else if(strncmp(optargp, "hard", sizeof("hard")-1) == 0) {
 
170
                        life_severity = life_hard;
 
171
                        optargp += sizeof("hard")-1;
 
172
                } else {
 
173
                        fprintf(stderr,
 
174
                                "%s: missing lifetime severity in %s, optargt=0p%p, optargp=0p%p, sizeof(\"soft\")=%d\n",
 
175
                                program_name,
 
176
                                optargt,
 
177
                                optargt,
 
178
                                optargp,
 
179
                                (int)sizeof("soft"));
 
180
                        usage(program_name, stderr);
 
181
                        return(1);
 
182
                }
 
183
                if(debug) {
 
184
                        fprintf(stdout,
 
185
                                "%s: debug: life_severity=%d, optargt=0p%p=\"%s\", optargp=0p%p=\"%s\", sizeof(\"soft\")=%d\n",
 
186
                                program_name,
 
187
                                life_severity,
 
188
                                optargt,
 
189
                                optargt,
 
190
                                optargp,
 
191
                                optargp,
 
192
                                (int)sizeof("soft"));
 
193
                }
 
194
                if(*(optargp++) != '-') {
 
195
                        fprintf(stderr,
 
196
                                "%s: expected '-' after severity of lifetime parameter to --life option.\n",
 
197
                                program_name);
 
198
                        usage(program_name, stderr);
 
199
                        return(1);
 
200
                }
 
201
                if(debug) {
 
202
                        fprintf(stdout,
 
203
                                "%s: debug: optargt=0p%p=\"%s\", optargp=0p%p=\"%s\", strlen(optargt)=%d, strlen(optargp)=%d, strncmp(optargp, \"addtime\", sizeof(\"addtime\")-1)=%d\n",
 
204
                                program_name,
 
205
                                optargt,
 
206
                                optargt,
 
207
                                optargp,
 
208
                                optargp,
 
209
                                (int)strlen(optargt),
 
210
                                (int)strlen(optargp),
 
211
                                strncmp(optargp, "addtime", sizeof("addtime")-1));
 
212
                }
 
213
                if(strncmp(optargp, "allocations", sizeof("allocations")-1) == 0) {
 
214
                        life_type = life_alloc;
 
215
                        optargp += sizeof("allocations")-1;
 
216
                } else if(strncmp(optargp, "bytes", sizeof("bytes")-1) == 0) {
 
217
                        life_type = life_bytes;
 
218
                        optargp += sizeof("bytes")-1;
 
219
                } else if(strncmp(optargp, "addtime", sizeof("addtime")-1) == 0) {
 
220
                        life_type = life_addtime;
 
221
                        optargp += sizeof("addtime")-1;
 
222
                } else if(strncmp(optargp, "usetime", sizeof("usetime")-1) == 0) {
 
223
                        life_type = life_usetime;
 
224
                        optargp += sizeof("usetime")-1;
 
225
                } else if(strncmp(optargp, "packets", sizeof("packets")-1) == 0) {
 
226
                        life_type = life_packets;
 
227
                        optargp += sizeof("packets")-1;
 
228
                } else {
 
229
                        fprintf(stderr,
 
230
                                "%s: missing lifetime type after '-' in %s\n",
 
231
                                program_name,
 
232
                                optargt);
 
233
                        usage(program_name, stderr);
 
234
                        return(1);
 
235
                }
 
236
                if(debug) {
 
237
                        fprintf(stdout,
 
238
                                "%s: debug: life_type=%d\n",
 
239
                                program_name,
 
240
                                life_type);
 
241
                }
 
242
                if(life_opt[life_severity][life_type] != NULL) {
 
243
                        fprintf(stderr,
 
244
                                "%s: Error, lifetime parameter redefined:%s, already defined as:0p%p\n",
 
245
                                program_name,
 
246
                                optargt,
 
247
                                life_opt[life_severity][life_type]);
 
248
                        return(1);
 
249
                }
 
250
                if(*(optargp++) != '=') {
 
251
                        fprintf(stderr,
 
252
                                "%s: expected '=' after type of lifetime parameter to --life option.\n",
 
253
                                program_name);
 
254
                        usage(program_name, stderr);
 
255
                        return(1);
 
256
                }
 
257
                if(debug) {
 
258
                        fprintf(stdout,
 
259
                                "%s: debug: optargt=0p%p, optargt+strlen(optargt)=0p%p, optargp=0p%p, strlen(optargp)=%d\n",
 
260
                                program_name,
 
261
                                optargt,
 
262
                                optargt+strlen(optargt),
 
263
                                optargp,
 
264
                                (int)strlen(optargp));
 
265
                }
 
266
                if(strlen(optargp) == 0) {
 
267
                        fprintf(stderr,
 
268
                                "%s: expected value after '=' in --life option. optargt=0p%p, optargt+strlen(optargt)=0p%p, optargp=0p%p\n",
 
269
                                program_name,
 
270
                                optargt,
 
271
                                optargt+strlen(optargt),
 
272
                                optargp);
 
273
                        usage(program_name, stderr);
 
274
                        return(1);
 
275
                }
 
276
                life[life_severity][life_type] = strtoul(optargp, &endptr, 0);
 
277
 
 
278
                if(!((endptr == optargp + strlen(optargp)) || (endptr == optargp + strcspn(optargp, ", ")))) {
 
279
                        fprintf(stderr,
 
280
                                "%s: Invalid character='%c' at offset %d in lifetime option parameter: '%s', parameter string is %d characters long, %d valid value characters found.\n",
 
281
                                program_name,
 
282
                                *endptr,
 
283
                                (int)(endptr - optarg),
 
284
                                optarg,
 
285
                                (int)strlen(optarg),
 
286
                                (int)(strcspn(optargp, ", ") - 1));
 
287
                        return(1);
 
288
                }
 
289
                life_opt[life_severity][life_type] = optargt;
 
290
                if(debug) {
 
291
                        fprintf(stdout, "%s lifetime %s set to %d.\n",
 
292
                                program_name, optargt, life[life_severity][life_type]);
 
293
                }
 
294
                optargp=endptr+1;
 
295
        } while(*endptr==',' || isspace(*endptr));
 
296
        
 
297
        return(0);
 
298
}
 
299
 
 
300
int
 
301
pfkey_register(uint8_t satype) {
 
302
        /* for registering SA types that can be negotiated */
 
303
        int error;
 
304
        ssize_t wlen;
 
305
        struct sadb_ext *extensions[SADB_EXT_MAX + 1];
 
306
        struct sadb_msg *pfkey_msg;
 
307
 
 
308
        pfkey_extensions_init(extensions);
 
309
        error = pfkey_msg_hdr_build(&extensions[0],
 
310
                                    SADB_REGISTER,
 
311
                                    satype,
 
312
                                    0,
 
313
                                    ++pfkey_seq,
 
314
                                    getpid());
 
315
        if(error != 0) {
 
316
                fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
 
317
                        program_name, error);
 
318
                pfkey_extensions_free(extensions);
 
319
                return(1);
 
320
        }
 
321
 
 
322
        error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
 
323
        if(error != 0) {
 
324
                fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
 
325
                        program_name, error);
 
326
                pfkey_extensions_free(extensions);
 
327
                pfkey_msg_free(&pfkey_msg);
 
328
                return(1);
 
329
        }
 
330
        wlen = write(pfkey_sock, pfkey_msg,
 
331
                     pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
 
332
        if(wlen != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) {
 
333
                /* cleanup code here */
 
334
                if(wlen < 0)
 
335
                        fprintf(stderr, "%s: Trouble writing to channel PF_KEY: %s\n",
 
336
                                program_name,
 
337
                                strerror(errno));
 
338
                else
 
339
                        fprintf(stderr, "%s: write to channel PF_KEY truncated.\n",
 
340
                                program_name);
 
341
                pfkey_extensions_free(extensions);
 
342
                pfkey_msg_free(&pfkey_msg);
 
343
                return(1);
 
344
        }
 
345
        pfkey_extensions_free(extensions);
 
346
        pfkey_msg_free(&pfkey_msg);
 
347
        
 
348
        return(0);
 
349
}
 
350
 
 
351
static struct option const longopts[] =
 
352
{
 
353
        {"ah", 1, 0, 'H'},
 
354
        {"esp", 1, 0, 'P'},
 
355
        {"comp", 1, 0, 'Z'},
 
356
        {"ip4", 0, 0, '4'},
 
357
        {"ip6", 0, 0, '6'},
 
358
        {"del", 0, 0, 'd'},
 
359
 
 
360
        {"authkey", 1, 0, 'A'},
 
361
        {"enckey", 1, 0, 'E'},
 
362
        {"edst", 1, 0, 'e'},
 
363
        {"spi", 1, 0, 's'},
 
364
        {"proto", 1, 0, 'p'},
 
365
        {"af", 1, 0, 'a'},
 
366
        {"replay_window", 1, 0, 'w'},
 
367
        {"iv", 1, 0, 'i'},
 
368
        {"dst", 1, 0, 'D'},
 
369
        {"src", 1, 0, 'S'},
 
370
        {"said", 1, 0, 'I'},
 
371
 
 
372
        {"help", 0, 0, 'h'},
 
373
        {"version", 0, 0, 'v'},
 
374
        {"clear", 0, 0, 'c'},
 
375
        {"label", 1, 0, 'l'},
 
376
        {"debug", 0, 0, 'g'},
 
377
        {"optionsfrom", 1, 0, '+'},
 
378
        {"life", 1, 0, 'f'},
 
379
        {"saref", 0, 0, 'r'},
 
380
        {"listenreply", 0, 0, 'R'},
 
381
        {0, 0, 0, 0}
 
382
};
 
383
 
 
384
int
 
385
main(int argc, char *argv[])
 
386
{
 
387
        char *endptr;
 
388
        __u32 spi = 0;
 
389
        int c, previous = -1;
 
390
/*      int ret; */
 
391
        ip_said said;
 
392
        size_t sa_len;
 
393
        const char* error_s;
 
394
        char ipaddr_txt[ADDRTOT_BUF];
 
395
        char ipsaid_txt[SATOT_BUF];
 
396
 
 
397
        int error = 0;
 
398
        ssize_t io_error;
 
399
        int argcount = argc;
 
400
        pid_t mypid;
 
401
        int listenreply = 0;
 
402
 
 
403
        unsigned char authalg, encryptalg;
 
404
        struct sadb_ext *extensions[SADB_EXT_MAX + 1];
 
405
        struct sadb_msg *pfkey_msg;
 
406
        char *iv_opt, *akey_opt, *ekey_opt, *alg_opt, *edst_opt, *spi_opt, *proto_opt, *af_opt, *said_opt, *dst_opt, *src_opt;
 
407
#if 0
 
408
        ip_address pfkey_address_p_ska;
 
409
        ip_address pfkey_ident_s_ska;
 
410
        ip_address pfkey_ident_d_ska;
 
411
#endif
 
412
        uint32_t life[life_maxsever][life_maxtype];
 
413
        char *life_opt[life_maxsever][life_maxtype];
 
414
        
 
415
        program_name = argv[0];
 
416
        mypid = getpid();
 
417
 
 
418
        memset(&said, 0, sizeof(said));
 
419
        iv_opt = akey_opt = ekey_opt = alg_opt = edst_opt = spi_opt = proto_opt = af_opt = said_opt = dst_opt = src_opt = NULL;
 
420
        {
 
421
                int i,j;
 
422
                for(i = 0; i < life_maxsever; i++) {
 
423
                        for(j = 0; j < life_maxtype; j++) {
 
424
                                life_opt[i][j] = NULL;
 
425
                                life[i][j] = 0;
 
426
                        }
 
427
                }
 
428
        }
 
429
 
 
430
        while((c = getopt_long(argc, argv, ""/*"H:P:Z:46dcA:E:e:s:a:w:i:D:S:hvgl:+:f:"*/, longopts, 0)) != EOF) {
 
431
                switch(c) {
 
432
                case 'g':
 
433
                        debug = 1;
 
434
                        pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX;
 
435
                        argcount--;
 
436
                        break;
 
437
 
 
438
                case 'R':
 
439
                        listenreply = 1;
 
440
                        argcount--;
 
441
                        break;
 
442
 
 
443
                case 'r':
 
444
                        saref = 1;
 
445
                        argcount--;
 
446
                        break;
 
447
 
 
448
                case 'l':
 
449
                        program_name = malloc(strlen(argv[0])
 
450
                                              + 10 /* update this when changing the sprintf() */
 
451
                                              + strlen(optarg));
 
452
                        sprintf(program_name, "%s --label %s",
 
453
                                argv[0],
 
454
                                optarg);
 
455
                        argcount -= 2;
 
456
                        break;
 
457
                case 'H':
 
458
                        if(alg) {
 
459
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
 
460
                                        program_name);
 
461
                                exit(1);
 
462
                        }
 
463
                        if       (!strcmp(optarg, "hmac-md5-96")) {
 
464
                                alg = XF_AHHMACMD5;
 
465
                        } else if(!strcmp(optarg, "hmac-sha1-96")) {
 
466
                                alg = XF_AHHMACSHA1;
 
467
                        } else {
 
468
                                fprintf(stderr, "%s: Unknown authentication algorithm '%s' follows '--ah' option.\n",
 
469
                                        program_name, optarg);
 
470
                                exit(1);
 
471
                        }
 
472
                        if(debug) {
 
473
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
474
                                        program_name,
 
475
                                        alg);
 
476
                        }
 
477
                        alg_opt = optarg;
 
478
                        break;
 
479
                case 'P':
 
480
                        if(alg) {
 
481
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
 
482
                                        program_name);
 
483
                                exit(1);
 
484
                        }
 
485
                        if       (!strcmp(optarg, "3des-md5-96")) {
 
486
                                alg = XF_ESP3DESMD596;
 
487
                        } else if(!strcmp(optarg, "3des-sha1-96")) {
 
488
                                alg = XF_ESP3DESSHA196;
 
489
                        } else if(!strcmp(optarg, "3des")) {
 
490
                                alg = XF_ESP3DES;
 
491
#ifdef KERNEL_ALG
 
492
                        } else if((alg_info=alg_info_esp_create_from_str(optarg, &alg_err, FALSE))) {
 
493
                                int esp_ealg_id, esp_aalg_id;
 
494
                                alg = XF_OTHER_ALG;
 
495
                                if (alg_info->alg_info_cnt>1) {
 
496
                                        fprintf(stderr, "%s: Invalid encryption algorithm '%s' "
 
497
                                                "follows '--esp' option: lead too many(%d) "
 
498
                                                "transforms\n",
 
499
                                                program_name, optarg, alg_info->alg_info_cnt);
 
500
                                        exit(1);
 
501
                                }
 
502
                                alg_string=optarg;
 
503
                                esp_info=&alg_info->esp[0];
 
504
                                if (debug) {
 
505
                                        fprintf(stdout, "%s: alg_info: cnt=%d ealg[0]=%d aalg[0]=%d\n",
 
506
                                                program_name, 
 
507
                                                alg_info->alg_info_cnt,
 
508
                                                esp_info->encryptalg,
 
509
                                                esp_info->authalg);
 
510
                                }
 
511
                                esp_ealg_id=esp_info->esp_ealg_id;
 
512
                                esp_aalg_id=esp_info->esp_aalg_id;
 
513
                                if (kernel_alg_proc_read()==0) {
 
514
                                        proc_read_ok++;
 
515
                                        if (!kernel_alg_esp_enc_ok(esp_ealg_id, 0, 0))
 
516
                                        {
 
517
                                                fprintf(stderr, "%s: ESP encryptalg=%d (\"%s\") "
 
518
                                                                "not present\n",
 
519
                                                        program_name,
 
520
                                                        esp_ealg_id,
 
521
                                                        enum_name(&esp_transformid_names, esp_ealg_id));
 
522
                                                exit(1);
 
523
                                        }
 
524
                                        if (!kernel_alg_esp_auth_ok(esp_aalg_id, 0))
 
525
                                        {
 
526
                                                fprintf(stderr, "%s: ESP authalg=%d (\"%s\")"
 
527
                                                                "not present\n",
 
528
                                                        program_name,
 
529
                                                        esp_aalg_id,
 
530
                                                        enum_name(&auth_alg_names, esp_aalg_id));
 
531
                                                exit(1);
 
532
                                        }
 
533
                                }
 
534
#endif /* KERNEL_ALG */
 
535
                        } else {
 
536
                                fprintf(stderr, "%s: Invalid encryption algorithm '%s' follows '--esp' option.\n",
 
537
                                        program_name, optarg);
 
538
                                exit(1);
 
539
                        }
 
540
                        if(debug) {
 
541
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
542
                                        program_name,
 
543
                                        alg);
 
544
                        }
 
545
                        alg_opt = optarg;
 
546
                        break;
 
547
                case 'Z':
 
548
                        if(alg) {
 
549
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
 
550
                                        program_name);
 
551
                                exit(1);
 
552
                        }
 
553
                        if       (!strcmp(optarg, "deflate")) {
 
554
                                alg = XF_COMPDEFLATE;
 
555
                        } else {
 
556
                                fprintf(stderr, "%s: Unknown compression algorithm '%s' follows '--comp' option.\n",
 
557
                                        program_name, optarg);
 
558
                                exit(1);
 
559
                        }
 
560
                        if(debug) {
 
561
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
562
                                        program_name,
 
563
                                        alg);
 
564
                        }
 
565
                        alg_opt = optarg;
 
566
                        break;
 
567
                case '4':
 
568
                        if(alg) {
 
569
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n",
 
570
                                        program_name);
 
571
                                exit(1);
 
572
                        }
 
573
                        alg = XF_IP4;
 
574
                        address_family = AF_INET;
 
575
                        if(debug) {
 
576
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
577
                                        program_name,
 
578
                                        alg);
 
579
                        }
 
580
                        alg_opt = optarg;
 
581
                        break;
 
582
                case '6':
 
583
                        if(alg) {
 
584
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n",
 
585
                                        program_name);
 
586
                                exit(1);
 
587
                        }
 
588
                        alg = XF_IP6;
 
589
                        address_family = AF_INET6;
 
590
                        if(debug) {
 
591
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
592
                                        program_name,
 
593
                                        alg);
 
594
                        }
 
595
                        alg_opt = optarg;
 
596
                        break;
 
597
                case 'd':
 
598
                        if(alg) {
 
599
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
 
600
                                        program_name);
 
601
                                exit(1);
 
602
                        }
 
603
                        alg = XF_DEL;
 
604
                        if(debug) {
 
605
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
606
                                        program_name,
 
607
                                        alg);
 
608
                        }
 
609
                        alg_opt = optarg;
 
610
                        break;
 
611
                case 'c':
 
612
                        if(alg) {
 
613
                                fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
 
614
                                        program_name);
 
615
                                exit(1);
 
616
                        }
 
617
                        alg = XF_CLR;
 
618
                        if(debug) {
 
619
                                fprintf(stdout, "%s: Algorithm %d selected.\n",
 
620
                                        program_name,
 
621
                                        alg);
 
622
                        }
 
623
                        alg_opt = optarg;
 
624
                        break;
 
625
                case 'e':
 
626
                        if(said_opt) {
 
627
                                fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n",
 
628
                                        program_name, optarg, said_opt);
 
629
                                exit (1);
 
630
                        }                               
 
631
                        if(edst_opt) {
 
632
                                fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n",
 
633
                                        program_name, optarg, edst_opt);
 
634
                                exit (1);
 
635
                        }
 
636
                        error_s = ttoaddr(optarg, 0, address_family, &edst);
 
637
                        if(error_s != NULL) {
 
638
                                if(error_s) {
 
639
                                        fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n",
 
640
                                                program_name, error_s, optarg);
 
641
                                        exit (1);
 
642
                                }
 
643
                        }
 
644
                        edst_opt = optarg;
 
645
                        if(debug) {
 
646
                                addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
647
                                fprintf(stdout, "%s: edst=%s.\n",
 
648
                                        program_name,
 
649
                                        ipaddr_txt);
 
650
                        }
 
651
                        break;
 
652
                case 's':
 
653
                        if(said_opt) {
 
654
                                fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n",
 
655
                                        program_name, optarg, said_opt);
 
656
                                exit (1);
 
657
                        }                               
 
658
                        if(spi_opt) {
 
659
                                fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n",
 
660
                                        program_name, optarg, spi_opt);
 
661
                                exit (1);
 
662
                        }                               
 
663
                        spi = strtoul(optarg, &endptr, 0);
 
664
                        if(!(endptr == optarg + strlen(optarg))) {
 
665
                                fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n",
 
666
                                        program_name, optarg);
 
667
                                exit (1);
 
668
                        }
 
669
                        if(spi < 0x100) {
 
670
                                fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n",
 
671
                                        program_name, optarg, spi);
 
672
                                exit(1);
 
673
                        }
 
674
                        spi_opt = optarg;
 
675
                        break;
 
676
                case 'p':
 
677
                        if(said_opt) {
 
678
                                fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n",
 
679
                                        program_name, optarg, said_opt);
 
680
                                exit (1);
 
681
                        }                               
 
682
                        if(proto_opt) {
 
683
                                fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n",
 
684
                                        program_name, optarg, proto_opt);
 
685
                                exit (1);
 
686
                        }
 
687
                        if(!strcmp(optarg, "ah"))
 
688
                                proto = SA_AH;
 
689
                        if(!strcmp(optarg, "esp"))
 
690
                                proto = SA_ESP;
 
691
                        if(!strcmp(optarg, "tun"))
 
692
                                proto = SA_IPIP;
 
693
                        if(!strcmp(optarg, "comp"))
 
694
                                proto = SA_COMP;
 
695
                        if(proto == 0) {
 
696
                                fprintf(stderr, "%s: Invalid PROTO parameter: %s\n",
 
697
                                        program_name, optarg);
 
698
                                exit (1);
 
699
                        }
 
700
                        proto_opt = optarg;
 
701
                        break;
 
702
                case 'a':
 
703
                        if(said_opt) {
 
704
                                fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined in SA:%s\n",
 
705
                                        program_name, optarg, said_opt);
 
706
                                exit (1);
 
707
                        }                               
 
708
                        if(af_opt) {
 
709
                                fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined as:%s\n",
 
710
                                        program_name, optarg, af_opt);
 
711
                                exit (1);
 
712
                        }
 
713
                        if(strcmp(optarg, "inet") == 0) {
 
714
                                address_family = AF_INET;
 
715
                                /* currently we ensure that all addresses belong to the same address family */
 
716
                                anyaddr(address_family, &dst);
 
717
                                anyaddr(address_family, &edst);
 
718
                                anyaddr(address_family, &src);
 
719
                        }
 
720
                        if(strcmp(optarg, "inet6") == 0) {
 
721
                                address_family = AF_INET6;
 
722
                                /* currently we ensure that all addresses belong to the same address family */
 
723
                                anyaddr(address_family, &dst);
 
724
                                anyaddr(address_family, &edst);
 
725
                                anyaddr(address_family, &src);
 
726
                        }
 
727
                        if((strcmp(optarg, "inet") != 0) && (strcmp(optarg, "inet6") != 0)) {
 
728
                                fprintf(stderr, "%s: Invalid ADDRESS FAMILY parameter: %s.\n",
 
729
                                        program_name, optarg);
 
730
                                exit (1);
 
731
                        }
 
732
                        af_opt = optarg;
 
733
                        break;
 
734
                case 'I':
 
735
                        if(said_opt) {
 
736
                                fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n",
 
737
                                        program_name, optarg, said_opt);
 
738
                                exit (1);
 
739
                        }                               
 
740
                        if(proto_opt) {
 
741
                                fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n",
 
742
                                        program_name, optarg, proto_opt);
 
743
                                exit (1);
 
744
                        }
 
745
                        if(edst_opt) {
 
746
                                fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n",
 
747
                                        program_name, optarg, edst_opt);
 
748
                                exit (1);
 
749
                        }
 
750
                        if(spi_opt) {
 
751
                                fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n",
 
752
                                        program_name, optarg, spi_opt);
 
753
                                exit (1);
 
754
                        }
 
755
                        error_s = ttosa(optarg, 0, &said);
 
756
                        if(error_s != NULL) {
 
757
                                fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
 
758
                                        program_name, error_s, optarg);
 
759
                                exit (1);
 
760
                        }
 
761
                        if(debug) {
 
762
                                satot(&said, 0, ipsaid_txt, sizeof(ipsaid_txt));
 
763
                                fprintf(stdout, "%s: said=%s.\n",
 
764
                                        program_name,
 
765
                                        ipsaid_txt);
 
766
                        }
 
767
                        /* init the src and dst with the same address family */
 
768
                        if(address_family == 0) {
 
769
                                address_family = addrtypeof(&said.dst);
 
770
                        } else if(address_family != addrtypeof(&said.dst)) {
 
771
                                fprintf(stderr, "%s: Error, specified address family (%d) is different that of SAID: %s\n",
 
772
                                        program_name, address_family, optarg);
 
773
                                exit (1);
 
774
                        }
 
775
                        anyaddr(address_family, &dst);
 
776
                        anyaddr(address_family, &edst);
 
777
                        anyaddr(address_family, &src);
 
778
                        said_opt = optarg;
 
779
                        break;
 
780
                case 'A':
 
781
                        if(optarg[0] == '0') {
 
782
                                switch(optarg[1]) {
 
783
                                case 't':
 
784
                                case 'x':
 
785
                                case 's':
 
786
                                        break;
 
787
                                default:
 
788
                                        fprintf(stderr, "%s: Authentication key must have a '0x', '0t' or '0s' prefix to select the format: %s\n",
 
789
                                                program_name, optarg);
 
790
                                        exit(1);
 
791
                                }
 
792
                        }
 
793
                        authkeylen = atodata(optarg, 0, NULL, 0);
 
794
                        if(!authkeylen) {
 
795
                                fprintf(stderr, "%s: unknown format or syntax error in authentication key: %s\n",
 
796
                                        program_name, optarg);
 
797
                                exit (1);
 
798
                        }
 
799
                        authkey = malloc(authkeylen);
 
800
                        if(authkey == NULL) {
 
801
                                fprintf(stderr, "%s: Memory allocation error.\n", program_name);
 
802
                                exit(1);
 
803
                        }
 
804
                        memset(authkey, 0, authkeylen);
 
805
                        authkeylen = atodata(optarg, 0, authkey, authkeylen);
 
806
                        akey_opt = optarg;
 
807
                        break;
 
808
                case 'E':
 
809
                        if(optarg[0] == '0') {
 
810
                                switch(optarg[1]) {
 
811
                                case 't':
 
812
                                case 'x':
 
813
                                case 's':
 
814
                                        break;
 
815
                                default:
 
816
                                        fprintf(stderr, "%s: Encryption key must have a '0x', '0t' or '0s' prefix to select the format: %s\n",
 
817
                                                program_name, optarg);
 
818
                                        exit(1);
 
819
                                }
 
820
                        }
 
821
                        enckeylen = atodata(optarg, 0, NULL, 0);
 
822
                        if(!enckeylen) {
 
823
                                fprintf(stderr, "%s: unknown format or syntax error in encryption key: %s\n",
 
824
                                        program_name, optarg);
 
825
                                exit (1);
 
826
                        }
 
827
                        enckey = malloc(enckeylen);
 
828
                        if(enckey == NULL) {
 
829
                                fprintf(stderr, "%s: Memory allocation error.\n", program_name);
 
830
                                exit(1);
 
831
                        }
 
832
                        memset(enckey, 0, enckeylen);
 
833
                        enckeylen = atodata(optarg, 0, enckey, enckeylen);
 
834
                        ekey_opt = optarg;
 
835
                        break;
 
836
                case 'w':
 
837
                        replay_window = strtoul(optarg, &endptr, 0);
 
838
                        if(!(endptr == optarg + strlen(optarg))) {
 
839
                                fprintf(stderr, "%s: Invalid character in replay_window parameter: %s\n",
 
840
                                        program_name, optarg);
 
841
                                exit (1);
 
842
                        }
 
843
                        if((replay_window < 0x1) || (replay_window > 64)) {
 
844
                                fprintf(stderr, "%s: Failed -- Illegal window size: arg=%s, replay_window=%d, must be 1 <= size <= 64.\n",
 
845
                                        program_name, optarg, replay_window);
 
846
                                exit(1);
 
847
                        }
 
848
                        break;
 
849
                case 'i':
 
850
                        if(optarg[0] == '0') {
 
851
                                switch(optarg[1]) {
 
852
                                case 't':
 
853
                                case 'x':
 
854
                                case 's':
 
855
                                        break;
 
856
                                default:
 
857
                                        fprintf(stderr, "%s: IV must have a '0x', '0t' or '0s' prefix to select the format, found '%c'.\n",
 
858
                                                program_name, optarg[1]);
 
859
                                        exit(1);
 
860
                                }
 
861
                        }
 
862
                        ivlen = atodata(optarg, 0, NULL, 0);
 
863
                        if(!ivlen) {
 
864
                                fprintf(stderr, "%s: unknown format or syntax error in IV: %s\n",
 
865
                                        program_name, optarg);
 
866
                                exit (1);
 
867
                        }
 
868
                        iv = malloc(ivlen);
 
869
                        if(iv == NULL) {
 
870
                                fprintf(stderr, "%s: Memory allocation error.\n", program_name);
 
871
                                exit(1);
 
872
                        }
 
873
                        memset(iv, 0, ivlen);
 
874
                        ivlen = atodata(optarg, 0, iv, ivlen);
 
875
                        iv_opt = optarg;
 
876
                        break;
 
877
                case 'D':
 
878
                        if(dst_opt) {
 
879
                                fprintf(stderr, "%s: Error, DST parameter redefined:%s, already defined as:%s\n",
 
880
                                        program_name, optarg, dst_opt);
 
881
                                exit (1);
 
882
                        }                               
 
883
                        error_s = ttoaddr(optarg, 0, address_family, &dst);
 
884
                        if(error_s != NULL) {
 
885
                                fprintf(stderr, "%s: Error, %s converting --dst argument:%s\n",
 
886
                                        program_name, error_s, optarg);
 
887
                                exit (1);
 
888
                        }
 
889
                        dst_opt = optarg;
 
890
                        if(debug) {
 
891
                                addrtot(&dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
892
                                fprintf(stdout, "%s: dst=%s.\n",
 
893
                                        program_name,
 
894
                                        ipaddr_txt);
 
895
                        }
 
896
                        break;
 
897
                case 'S':
 
898
                        if(src_opt) {
 
899
                                fprintf(stderr, "%s: Error, SRC parameter redefined:%s, already defined as:%s\n",
 
900
                                        program_name, optarg, src_opt);
 
901
                                exit (1);
 
902
                        }                               
 
903
                        error_s = ttoaddr(optarg, 0, address_family, &src);
 
904
                        if(error_s != NULL) {
 
905
                                fprintf(stderr, "%s: Error, %s converting --src argument:%s\n",
 
906
                                        program_name, error_s, optarg);
 
907
                                exit (1);
 
908
                        }
 
909
                        src_opt = optarg;
 
910
                        if(debug) {
 
911
                                addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
912
                                fprintf(stdout, "%s: src=%s.\n",
 
913
                                        program_name,
 
914
                                        ipaddr_txt);
 
915
                        }
 
916
                        break;
 
917
                case 'h':
 
918
                        usage(program_name, stdout);
 
919
                        exit(0);
 
920
                case '?':
 
921
                        usage(program_name, stderr);
 
922
                        exit(1);
 
923
                case 'v':
 
924
                        fprintf(stdout, "%s, %s\n", program_name, spi_c_version);
 
925
                        exit(1);
 
926
                case '+': /* optionsfrom */
 
927
                        optionsfrom(optarg, &argc, &argv, optind, stderr);
 
928
                        /* no return on error */
 
929
                        break;
 
930
                case 'f':
 
931
                        if(parse_life_options(life,
 
932
                                           life_opt,
 
933
                                           optarg) != 0) {
 
934
                                exit(1);
 
935
                        };
 
936
                        break;
 
937
                default:
 
938
                        fprintf(stderr, "%s: unrecognized option '%c', update option processing.\n",
 
939
                                program_name, c);
 
940
                        exit(1);
 
941
                }
 
942
                previous = c;
 
943
        }
 
944
        if(debug) {
 
945
                fprintf(stdout, "%s: All options processed.\n",
 
946
                                program_name);
 
947
        }
 
948
 
 
949
        if(argcount == 1) {
 
950
                system("cat /proc/net/ipsec_spi");
 
951
                exit(0);
 
952
        }
 
953
 
 
954
        switch(alg) {
 
955
#ifdef KERNEL_ALG
 
956
        case XF_OTHER_ALG: 
 
957
                /* validate keysizes */
 
958
                if (proc_read_ok) {
 
959
                       const struct sadb_alg *alg_p;
 
960
                       int keylen, minbits, maxbits;
 
961
                       alg_p=kernel_alg_sadb_alg_get(SADB_SATYPE_ESP,SADB_EXT_SUPPORTED_ENCRYPT, 
 
962
                                       esp_info->encryptalg);
 
963
                       assert(alg_p);
 
964
                       keylen=enckeylen * 8;
 
965
 
 
966
                       if (alg_p->sadb_alg_id==ESP_3DES || alg_p->sadb_alg_id==ESP_DES) {
 
967
                               maxbits=minbits=alg_p->sadb_alg_minbits * 8 /7;
 
968
                       } else {
 
969
                               minbits=alg_p->sadb_alg_minbits;
 
970
                               maxbits=alg_p->sadb_alg_maxbits;
 
971
                       }
 
972
                       /* 
 
973
                        * if explicit keylen told in encrypt algo, eg "aes128"
 
974
                        * check actual keylen "equality"
 
975
                        */
 
976
                       if (esp_info->esp_ealg_keylen &&
 
977
                               esp_info->esp_ealg_keylen!=keylen) {
 
978
                               fprintf(stderr, "%s: invalid encryption keylen=%d, "
 
979
                                               "required %d by encrypt algo string=\"%s\"\n",
 
980
                                       program_name, 
 
981
                                       keylen,
 
982
                                       (int)esp_info->esp_ealg_keylen,
 
983
                                       alg_string);
 
984
                               exit(1);
 
985
 
 
986
                       }
 
987
                       /* thanks DES for this sh*t */
 
988
 
 
989
                       if (minbits > keylen || maxbits < keylen) {
 
990
                               fprintf(stderr, "%s: invalid encryption keylen=%d, "
 
991
                                               "must be between %d and %d bits\n",
 
992
                                               program_name, 
 
993
                                               keylen, minbits, maxbits);
 
994
                               exit(1);
 
995
                       }
 
996
                       alg_p=kernel_alg_sadb_alg_get(SADB_SATYPE_ESP,SADB_EXT_SUPPORTED_AUTH, 
 
997
                                       esp_info->authalg);
 
998
                       assert(alg_p);
 
999
                       keylen=authkeylen * 8;
 
1000
                       minbits=alg_p->sadb_alg_minbits;
 
1001
                       maxbits=alg_p->sadb_alg_maxbits;
 
1002
                       if (minbits > keylen || maxbits < keylen) {
 
1003
                               fprintf(stderr, "%s: invalid auth keylen=%d, "
 
1004
                                               "must be between %d and %d bits\n",
 
1005
                                               program_name, 
 
1006
                                               keylen, minbits, maxbits);
 
1007
                               exit(1);
 
1008
                       }
 
1009
 
 
1010
                }
 
1011
#endif /* KERNEL_ALG */
 
1012
        case XF_IP4:
 
1013
        case XF_IP6:
 
1014
        case XF_DEL:
 
1015
        case XF_AHHMACMD5:
 
1016
        case XF_AHHMACSHA1:
 
1017
        case XF_ESP3DESMD596:
 
1018
        case XF_ESP3DESSHA196:
 
1019
        case XF_ESP3DES:
 
1020
        case XF_COMPDEFLATE:
 
1021
                if(!said_opt) {
 
1022
                        if(isanyaddr(&edst)) {
 
1023
                                fprintf(stderr, "%s: SA destination not specified.\n",
 
1024
                                        program_name);
 
1025
                                exit(1);
 
1026
                        }
 
1027
                        if(!spi) {
 
1028
                                fprintf(stderr, "%s: SA SPI not specified.\n",
 
1029
                                        program_name);
 
1030
                                exit(1);
 
1031
                        }
 
1032
                        if(!proto) {
 
1033
                                fprintf(stderr, "%s: SA PROTO not specified.\n",
 
1034
                                        program_name);
 
1035
                                exit(1);
 
1036
                        }
 
1037
                        initsaid(&edst, htonl(spi), proto, &said);
 
1038
                } else {
 
1039
                        proto = said.proto;
 
1040
                        spi = ntohl(said.spi);
 
1041
                        edst = said.dst;
 
1042
                }
 
1043
                if((address_family != 0) && (address_family != addrtypeof(&said.dst))) {
 
1044
                        fprintf(stderr, "%s: Defined address family and address family of SA missmatch.\n",
 
1045
                                program_name);
 
1046
                        exit(1);
 
1047
                }
 
1048
                sa_len = satot(&said, 0, sa, sizeof(sa));
 
1049
 
 
1050
                if(debug) {
 
1051
                        fprintf(stdout, "%s: SA valid.\n",
 
1052
                                program_name);
 
1053
                }
 
1054
                break;
 
1055
        case XF_CLR:
 
1056
                break;
 
1057
        default:
 
1058
                fprintf(stderr, "%s: No action chosen.  See '%s --help' for usage.\n",
 
1059
                        program_name, program_name);
 
1060
                exit(1);
 
1061
        }
 
1062
 
 
1063
        switch(alg) {
 
1064
        case XF_CLR:
 
1065
        case XF_DEL:
 
1066
        case XF_IP4:
 
1067
        case XF_IP6:
 
1068
        case XF_AHHMACMD5:
 
1069
        case XF_AHHMACSHA1:
 
1070
        case XF_ESP3DESMD596:
 
1071
        case XF_ESP3DESSHA196:
 
1072
        case XF_ESP3DES:
 
1073
        case XF_COMPDEFLATE:
 
1074
#ifdef KERNEL_ALG
 
1075
        case XF_OTHER_ALG:
 
1076
#endif /* NO_KERNEL_ALG */
 
1077
                break;
 
1078
        default:
 
1079
                fprintf(stderr, "%s: No action chosen.  See '%s --help' for usage.\n",
 
1080
                        program_name, program_name);
 
1081
                exit(1);
 
1082
        }
 
1083
        if(debug) {
 
1084
                fprintf(stdout, "%s: Algorithm ok.\n",
 
1085
                        program_name);
 
1086
        }
 
1087
 
 
1088
        if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
 
1089
                fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ",
 
1090
                        program_name);
 
1091
                switch(errno) {
 
1092
                case ENOENT:
 
1093
                        fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
 
1094
                        break;
 
1095
                case EACCES:
 
1096
                        fprintf(stderr, "access denied.  ");
 
1097
                        if(getuid() == 0) {
 
1098
                                fprintf(stderr, "Check permissions.  Should be 600.\n");
 
1099
                        } else {
 
1100
                                fprintf(stderr, "You must be root to open this file.\n");
 
1101
                        }
 
1102
                        break;
 
1103
                case EUNATCH:
 
1104
                        fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
 
1105
                        break;
 
1106
                case ENODEV:
 
1107
                        fprintf(stderr, "KLIPS not loaded or enabled.\n");
 
1108
                        break;
 
1109
                case EBUSY:
 
1110
                        fprintf(stderr, "KLIPS is busy.  Most likely a serious internal error occured in a previous command.  Please report as much detail as possible to development team.\n");
 
1111
                        break;
 
1112
                case EINVAL:
 
1113
                        fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
 
1114
                        break;
 
1115
                case ENOBUFS:
 
1116
                        fprintf(stderr, "No kernel memory to allocate SA.\n");
 
1117
                        break;
 
1118
                case ESOCKTNOSUPPORT:
 
1119
                        fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
 
1120
                        break;
 
1121
                case EEXIST:
 
1122
                        fprintf(stderr, "SA already in use.  Delete old one first.\n");
 
1123
                        break;
 
1124
                case ENXIO:
 
1125
                        fprintf(stderr, "SA does not exist.  Cannot delete.\n");
 
1126
                        break;
 
1127
                case EAFNOSUPPORT:
 
1128
                        fprintf(stderr, "KLIPS not loaded or enabled.\n");
 
1129
                        break;
 
1130
                default:
 
1131
                        fprintf(stderr, "Unknown file open error %d.  Please report as much detail as possible to development team.\n", errno);
 
1132
                }
 
1133
                exit(1);
 
1134
        }
 
1135
 
 
1136
#ifdef MANUAL_IS_NOT_ABLE_TO_NEGOTIATE
 
1137
        /* for registering SA types that can be negotiated */
 
1138
        if(pfkey_register(SADB_SATYPE_AH) != 0) {
 
1139
                exit(1);
 
1140
        }
 
1141
        if(pfkey_register(SADB_SATYPE_ESP) != 0) {
 
1142
                exit(1);
 
1143
        }
 
1144
        if(pfkey_register(SADB_X_SATYPE_IPIP) != 0) {
 
1145
                exit(1);
 
1146
        }
 
1147
        if(pfkey_register(SADB_X_SATYPE_COMP) != 0) {
 
1148
                exit(1);
 
1149
        }
 
1150
#endif /* MANUAL_IS_NOT_ABLE_TO_NEGOTIATE */
 
1151
 
 
1152
        /* Build an SADB_ADD message to send down. */
 
1153
        /* It needs <base, SA, address(SD), key(AE)> minimum. */
 
1154
        /*   Lifetime(HS) could be added before addresses. */
 
1155
        pfkey_extensions_init(extensions);
 
1156
        if(debug) {
 
1157
                fprintf(stdout, "%s: extensions=0p%p &extensions=0p%p extensions[0]=0p%p &extensions[0]=0p%p cleared.\n",
 
1158
                        program_name,
 
1159
                        extensions,
 
1160
                        &extensions,
 
1161
                        extensions[0],
 
1162
                        &extensions[0]);
 
1163
        }
 
1164
        if((error = pfkey_msg_hdr_build(&extensions[0],
 
1165
                                        (alg == XF_DEL ? SADB_DELETE : alg == XF_CLR ? SADB_FLUSH : SADB_ADD),
 
1166
                                        proto2satype(proto),
 
1167
                                        0,
 
1168
                                        ++pfkey_seq,
 
1169
                                        mypid))) {
 
1170
                fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
 
1171
                        program_name, error);
 
1172
                pfkey_extensions_free(extensions);
 
1173
                exit(1);
 
1174
        }
 
1175
        if(debug) {
 
1176
                fprintf(stdout, "%s: extensions=0p%p &extensions=0p%p extensions[0]=0p%p &extensions[0]=0p%p set w/msghdr.\n",
 
1177
                        program_name,
 
1178
                        extensions,
 
1179
                        &extensions,
 
1180
                        extensions[0],
 
1181
                        &extensions[0]);
 
1182
        }
 
1183
        if(debug) {
 
1184
                fprintf(stdout, "%s: base message assembled.\n", program_name);
 
1185
        }
 
1186
        
 
1187
        switch(alg) {
 
1188
        case XF_AHHMACMD5:
 
1189
        case XF_ESP3DESMD596:
 
1190
                authalg = SADB_AALG_MD5HMAC;
 
1191
                break;
 
1192
        case XF_AHHMACSHA1:
 
1193
        case XF_ESP3DESSHA196:
 
1194
                authalg = SADB_AALG_SHA1HMAC;
 
1195
                break;
 
1196
#ifdef KERNEL_ALG
 
1197
        case XF_OTHER_ALG:
 
1198
                authalg= esp_info->authalg;
 
1199
                if(debug) {
 
1200
                        fprintf(stdout, "%s: debug: authalg=%d\n",
 
1201
                                program_name, authalg);
 
1202
                }
 
1203
                break;
 
1204
#endif /* KERNEL_ALG */
 
1205
        case XF_ESP3DESMD5:
 
1206
        default:
 
1207
                authalg = SADB_AALG_NONE;
 
1208
        }
 
1209
        switch(alg) {
 
1210
        case XF_ESP3DES:
 
1211
        case XF_ESP3DESMD596:
 
1212
        case XF_ESP3DESSHA196:
 
1213
                encryptalg = SADB_EALG_3DESCBC;
 
1214
                break;
 
1215
        case XF_COMPDEFLATE:
 
1216
                encryptalg = SADB_X_CALG_DEFLATE;
 
1217
                break;
 
1218
#ifdef KERNEL_ALG
 
1219
        case XF_OTHER_ALG:
 
1220
                encryptalg= esp_info->encryptalg;
 
1221
                if(debug) {
 
1222
                        fprintf(stdout, "%s: debug: encryptalg=%d\n",
 
1223
                                program_name, encryptalg);
 
1224
                }
 
1225
                break;
 
1226
#endif /* KERNEL_ALG */
 
1227
        default:
 
1228
                encryptalg = SADB_EALG_NONE;
 
1229
        }
 
1230
        if(!(alg == XF_CLR /* IE: pfkey_msg->sadb_msg_type == SADB_FLUSH */)) {
 
1231
                if((error = pfkey_sa_build(&extensions[SADB_EXT_SA],
 
1232
                                           SADB_EXT_SA,
 
1233
                                           htonl(spi), /* in network order */
 
1234
                                           replay_window,
 
1235
                                           SADB_SASTATE_MATURE,
 
1236
                                           authalg,
 
1237
                                           encryptalg,
 
1238
                                           0))) {
 
1239
                        fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n",
 
1240
                                program_name, error);
 
1241
                        pfkey_extensions_free(extensions);
 
1242
                        exit(1);
 
1243
                }
 
1244
                if(debug) {
 
1245
                        fprintf(stdout, "%s: extensions[0]=0p%p previously set with msg_hdr.\n",
 
1246
                                program_name,
 
1247
                                extensions[0]);
 
1248
                }
 
1249
                if(debug) {
 
1250
                        fprintf(stdout, "%s: assembled SA extension, pfkey msg authalg=%d encalg=%d.\n",
 
1251
                                program_name,
 
1252
                                authalg,
 
1253
                                encryptalg);
 
1254
                }
 
1255
                
 
1256
                if(debug) {
 
1257
                        int i,j;
 
1258
                        for(i = 0; i < life_maxsever; i++) {
 
1259
                                for(j = 0; j < life_maxtype; j++) {
 
1260
                                        fprintf(stdout, "%s: i=%d, j=%d, life_opt[%d][%d]=0p%p, life[%d][%d]=%d\n",
 
1261
                                                program_name,
 
1262
                                                i, j, i, j, life_opt[i][j], i, j, life[i][j]);
 
1263
                                }
 
1264
                        }
 
1265
                }
 
1266
                if(life_opt[life_soft][life_alloc] != NULL ||
 
1267
                   life_opt[life_soft][life_bytes] != NULL ||
 
1268
                   life_opt[life_soft][life_addtime] != NULL ||
 
1269
                   life_opt[life_soft][life_usetime] != NULL ||
 
1270
                   life_opt[life_soft][life_packets] != NULL) {
 
1271
                        if((error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT],
 
1272
                                                         SADB_EXT_LIFETIME_SOFT,
 
1273
                                                         life[life_soft][life_alloc],/*-1,*/            /*allocations*/
 
1274
                                                         life[life_soft][life_bytes],/*-1,*/            /*bytes*/
 
1275
                                                         life[life_soft][life_addtime],/*-1,*/          /*addtime*/
 
1276
                                                         life[life_soft][life_usetime],/*-1,*/          /*usetime*/
 
1277
                                                         life[life_soft][life_packets]/*-1*/))) {       /*packets*/
 
1278
                                fprintf(stderr, "%s: Trouble building lifetime_s extension, error=%d.\n",
 
1279
                                        program_name, error);
 
1280
                                pfkey_extensions_free(extensions);
 
1281
                                exit(1);
 
1282
                        }
 
1283
                        if(debug) {
 
1284
                                fprintf(stdout, "%s: lifetime_s extension assembled.\n",
 
1285
                                        program_name);
 
1286
                        }
 
1287
                }
 
1288
 
 
1289
                if(life_opt[life_hard][life_alloc] != NULL ||
 
1290
                   life_opt[life_hard][life_bytes] != NULL ||
 
1291
                   life_opt[life_hard][life_addtime] != NULL ||
 
1292
                   life_opt[life_hard][life_usetime] != NULL ||
 
1293
                   life_opt[life_hard][life_packets] != NULL) {
 
1294
                        if((error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD],
 
1295
                                                         SADB_EXT_LIFETIME_HARD,
 
1296
                                                         life[life_hard][life_alloc],/*-1,*/            /*allocations*/
 
1297
                                                         life[life_hard][life_bytes],/*-1,*/            /*bytes*/
 
1298
                                                         life[life_hard][life_addtime],/*-1,*/          /*addtime*/
 
1299
                                                         life[life_hard][life_usetime],/*-1,*/          /*usetime*/
 
1300
                                                         life[life_hard][life_packets]/*-1*/))) {       /*packets*/
 
1301
                                fprintf(stderr, "%s: Trouble building lifetime_h extension, error=%d.\n",
 
1302
                                        program_name, error);
 
1303
                                pfkey_extensions_free(extensions);
 
1304
                                exit(1);
 
1305
                        }
 
1306
                        if(debug) {
 
1307
                                fprintf(stdout, "%s: lifetime_h extension assembled.\n",
 
1308
                                        program_name);
 
1309
                        }
 
1310
                }
 
1311
                
 
1312
                if(debug) {
 
1313
                        addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1314
                        fprintf(stdout, "%s: assembling address_s extension (%s).\n",
 
1315
                                program_name, ipaddr_txt);
 
1316
                }
 
1317
        
 
1318
                if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
 
1319
                                                SADB_EXT_ADDRESS_SRC,
 
1320
                                                0,
 
1321
                                                0,
 
1322
                                                sockaddrof(&src)))) {
 
1323
                        addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1324
                        fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n",
 
1325
                                program_name, ipaddr_txt, error);
 
1326
                        pfkey_extensions_free(extensions);
 
1327
                        exit(1);
 
1328
                }
 
1329
                if(debug) {
 
1330
                        ip_address temp_addr;
 
1331
                        
 
1332
                        switch(address_family) {
 
1333
                                case AF_INET:
 
1334
                                        initaddr((const unsigned char *)&(((struct sockaddr_in*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_SRC])) + 1))->sin_addr),
 
1335
                                                sockaddrlenof(&src), address_family, &temp_addr);
 
1336
                                        break;
 
1337
                                case AF_INET6:
 
1338
                                        initaddr((const unsigned char *)&(((struct sockaddr_in6*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_SRC])) + 1))->sin6_addr),
 
1339
                                                sockaddrlenof(&src), address_family, &temp_addr);
 
1340
                                        break;
 
1341
                                default:
 
1342
                                        fprintf(stdout, "%s: unknown address family (%d).\n",
 
1343
                                                program_name, address_family);
 
1344
                                        exit(1);
 
1345
                        }
 
1346
                        addrtot(&temp_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1347
                        fprintf(stdout, "%s: address_s extension assembled (%s).\n",
 
1348
                                program_name, ipaddr_txt);
 
1349
                }
 
1350
        
 
1351
                if(debug) {
 
1352
                        addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1353
                        fprintf(stdout, "%s: assembling address_d extension (%s).\n",
 
1354
                                program_name, ipaddr_txt);
 
1355
                }
 
1356
        
 
1357
                if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
 
1358
                                                SADB_EXT_ADDRESS_DST,
 
1359
                                                0,
 
1360
                                                0,
 
1361
                                                sockaddrof(&edst)))) {
 
1362
                        addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1363
                        fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n",
 
1364
                                program_name, ipaddr_txt, error);
 
1365
                        pfkey_extensions_free(extensions);
 
1366
                        exit(1);
 
1367
                }
 
1368
                if(debug) {
 
1369
                        ip_address temp_addr;
 
1370
                        switch(address_family) {
 
1371
                                case AF_INET:
 
1372
                                        initaddr((const unsigned char *)&(((struct sockaddr_in*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_DST])) + 1))->sin_addr),
 
1373
                                                4, address_family, &temp_addr);
 
1374
                                        break;
 
1375
                                case AF_INET6:
 
1376
                                        initaddr((const unsigned char *)&(((struct sockaddr_in6*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_DST])) + 1))->sin6_addr),
 
1377
                                                16, address_family, &temp_addr);
 
1378
                                        break;
 
1379
                                default:
 
1380
                                        fprintf(stdout, "%s: unknown address family (%d).\n",
 
1381
                                                program_name, address_family);
 
1382
                                        exit(1);
 
1383
                        }
 
1384
                        addrtot(&temp_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
 
1385
                        fprintf(stdout, "%s: address_d extension assembled (%s).\n",
 
1386
                                program_name, ipaddr_txt);
 
1387
                }
 
1388
 
 
1389
#if PFKEY_PROXY
 
1390
                anyaddr(address_family, &pfkey_address_p_ska);
 
1391
                if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY],
 
1392
                                                SADB_EXT_ADDRESS_PROXY,
 
1393
                                                0,
 
1394
                                                0,
 
1395
                                                sockaddrof(&pfkey_address_p_ska)))) {
 
1396
                        fprintf(stderr, "%s: Trouble building address_p extension, error=%d.\n",
 
1397
                                program_name, error);
 
1398
                        pfkey_extensions_free(extensions);
 
1399
                        exit(1);
 
1400
                }
 
1401
                if(debug) {
 
1402
                        fprintf(stdout, "%s: address_p extension assembled.\n", program_name);
 
1403
                }
 
1404
#endif /* PFKEY_PROXY */
 
1405
                
 
1406
                switch(alg) {
 
1407
#ifdef KERNEL_ALG
 
1408
                /*      Allow no auth ... after all is local root decision 8)  */
 
1409
                case XF_OTHER_ALG:
 
1410
                        if (!authalg)
 
1411
                                break;
 
1412
#endif /* KERNEL_ALG */
 
1413
                case XF_AHHMACMD5:
 
1414
                case XF_ESP3DESMD596:
 
1415
                case XF_AHHMACSHA1:
 
1416
                case XF_ESP3DESSHA196:
 
1417
                        if((error = pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH],
 
1418
                                                    SADB_EXT_KEY_AUTH,
 
1419
                                                    authkeylen * 8,
 
1420
                                                    authkey))) {
 
1421
                                fprintf(stderr, "%s: Trouble building key_a extension, error=%d.\n",
 
1422
                                        program_name, error);
 
1423
                                pfkey_extensions_free(extensions);
 
1424
                                exit(1);
 
1425
                        }
 
1426
                        if(debug) {
 
1427
                                fprintf(stdout, "%s: key_a extension assembled.\n",
 
1428
                                        program_name);
 
1429
                        }
 
1430
                        break;
 
1431
                default:
 
1432
                        break;
 
1433
                }
 
1434
                
 
1435
                switch(alg) {
 
1436
                case XF_ESP3DES:
 
1437
                case XF_ESP3DESMD596:
 
1438
                case XF_ESP3DESSHA196:
 
1439
#ifdef KERNEL_ALG
 
1440
                case XF_OTHER_ALG:
 
1441
#endif /* KERNEL_ALG */
 
1442
                        if((error = pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT],
 
1443
                                                    SADB_EXT_KEY_ENCRYPT,
 
1444
                                                    enckeylen * 8,
 
1445
                                                    enckey))) {
 
1446
                                fprintf(stderr, "%s: Trouble building key_e extension, error=%d.\n",
 
1447
                                        program_name, error);
 
1448
                                pfkey_extensions_free(extensions);
 
1449
                                exit(1);
 
1450
                        }
 
1451
                        if(debug) {
 
1452
                                fprintf(stdout, "%s: key_e extension assembled.\n",
 
1453
                                        program_name);
 
1454
                        }
 
1455
                        break;
 
1456
                default:
 
1457
                        break;
 
1458
                }
 
1459
                
 
1460
#ifdef PFKEY_IDENT /* GG: looks wierd, not touched */
 
1461
                if((pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC],
 
1462
                                      SADB_EXT_IDENTITY_SRC,
 
1463
                                      SADB_IDENTTYPE_PREFIX,
 
1464
                                      0,
 
1465
                                      strlen(pfkey_ident_s_ska),
 
1466
                                      pfkey_ident_s_ska))) {
 
1467
                        fprintf(stderr, "%s: Trouble building ident_s extension, error=%d.\n",
 
1468
                                program_name, error);
 
1469
                        pfkey_extensions_free(extensions);
 
1470
                        exit(1);
 
1471
                }
 
1472
                if(subnettoa(addr, mask, format, pfkey_ident_s_ska,
 
1473
                             sizeof(pfkey_ident_s_ska) ) !=
 
1474
                   sizeof(pfkey_ident_s_ska) ) {
 
1475
                        exit (1);
 
1476
                }
 
1477
                
 
1478
                if((error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST],
 
1479
                                              SADB_EXT_IDENTITY_DST,
 
1480
                                              SADB_IDENTTYPE_PREFIX,
 
1481
                                              0,
 
1482
                                              strlen(pfkey_ident_d_ska),
 
1483
                                              pfkey_ident_d_ska))) {
 
1484
                        fprintf(stderr, "%s: Trouble building ident_d extension, error=%d.\n",
 
1485
                                program_name, error);
 
1486
                        pfkey_extensions_free(extensions);
 
1487
                        exit(1);
 
1488
                }
 
1489
                if(subnettoa(addr, mask, format, pfkey_ident_d_ska,
 
1490
                             sizeof(pfkey_ident_d_ska) ) !=
 
1491
                   sizeof(pfkey_ident_d_ska) ) {
 
1492
                        exit (1);
 
1493
                }
 
1494
 
 
1495
                if(debug) {
 
1496
                        fprintf(stdout, "%s: ident extensions assembled.\n",
 
1497
                                program_name);
 
1498
                }
 
1499
#endif /* PFKEY_IDENT */
 
1500
        }
 
1501
        
 
1502
        if(debug) {
 
1503
                fprintf(stdout, "%s: assembling pfkey msg....\n",
 
1504
                        program_name);
 
1505
        }
 
1506
        if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
 
1507
                fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
 
1508
                        program_name, error);
 
1509
                pfkey_extensions_free(extensions);
 
1510
                pfkey_msg_free(&pfkey_msg);
 
1511
                exit(1);
 
1512
        }
 
1513
        if(debug) {
 
1514
                fprintf(stdout, "%s: assembled.\n",
 
1515
                        program_name);
 
1516
        }
 
1517
        if(debug) {
 
1518
                fprintf(stdout, "%s: writing pfkey msg.\n",
 
1519
                        program_name);
 
1520
        }
 
1521
        io_error = write(pfkey_sock,
 
1522
                         pfkey_msg,
 
1523
                         pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
 
1524
        if(io_error < 0) {
 
1525
                fprintf(stderr, "%s: pfkey write failed (errno=%d): ",
 
1526
                        program_name, errno);
 
1527
                pfkey_extensions_free(extensions);
 
1528
                pfkey_msg_free(&pfkey_msg);
 
1529
                switch(errno) {
 
1530
                case EACCES:
 
1531
                        fprintf(stderr, "access denied.  ");
 
1532
                        if(getuid() == 0) {
 
1533
                                fprintf(stderr, "Check permissions.  Should be 600.\n");
 
1534
                        } else {
 
1535
                                fprintf(stderr, "You must be root to open this file.\n");
 
1536
                        }
 
1537
                        break;
 
1538
                case EUNATCH:
 
1539
                        fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
 
1540
                        break;
 
1541
                case EBUSY:
 
1542
                        fprintf(stderr, "KLIPS is busy.  Most likely a serious internal error occured in a previous command.  Please report as much detail as possible to development team.\n");
 
1543
                        break;
 
1544
                case EINVAL:
 
1545
                        fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
 
1546
                        break;
 
1547
                case ENODEV:
 
1548
                        fprintf(stderr, "KLIPS not loaded or enabled.\n");
 
1549
                        fprintf(stderr, "No device?!?\n");
 
1550
                        break;
 
1551
                case ENOBUFS:
 
1552
                        fprintf(stderr, "No kernel memory to allocate SA.\n");
 
1553
                        break;
 
1554
                case ESOCKTNOSUPPORT:
 
1555
                        fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
 
1556
                        break;
 
1557
                case EEXIST:
 
1558
                        fprintf(stderr, "SA already in use.  Delete old one first.\n");
 
1559
                        break;
 
1560
                case ENOENT:
 
1561
                        fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
 
1562
                        break;
 
1563
                case ENXIO:
 
1564
                case ESRCH:
 
1565
                        fprintf(stderr, "SA does not exist.  Cannot delete.\n");
 
1566
                        break;
 
1567
                case ENOSPC:
 
1568
                        fprintf(stderr, "no room in kernel SAref table.  Cannot process request.\n");
 
1569
                        break;
 
1570
                case ESPIPE:
 
1571
                        fprintf(stderr, "kernel SAref table internal error.  Cannot process request.\n");
 
1572
                        break;
 
1573
                default:
 
1574
                        fprintf(stderr, "Unknown socket write error %d (%s).  Please report as much detail as possible to development team.\n",
 
1575
                                errno, strerror(errno));
 
1576
                }
 
1577
                exit(1);
 
1578
        } else if (io_error != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) {
 
1579
                fprintf(stderr, "%s: pfkey write truncated to %d bytes\n",
 
1580
                        program_name, (int)io_error);
 
1581
                pfkey_extensions_free(extensions);
 
1582
                pfkey_msg_free(&pfkey_msg);
 
1583
                exit(1);
 
1584
        }
 
1585
 
 
1586
        if(debug) {
 
1587
                fprintf(stdout, "%s: pfkey command written to socket.\n",
 
1588
                        program_name);
 
1589
        }
 
1590
 
 
1591
        if(pfkey_msg) {
 
1592
                pfkey_extensions_free(extensions);
 
1593
                pfkey_msg_free(&pfkey_msg);
 
1594
        }
 
1595
        if(debug) {
 
1596
                fprintf(stdout, "%s: pfkey message buffer freed.\n",
 
1597
                        program_name);
 
1598
        }
 
1599
        if(authkey) {
 
1600
                memset((caddr_t)authkey, 0, authkeylen);
 
1601
                free(authkey);
 
1602
        }
 
1603
        if(enckey) {
 
1604
                memset((caddr_t)enckey, 0, enckeylen);
 
1605
                free(enckey);
 
1606
        }
 
1607
        if(iv) {
 
1608
                memset((caddr_t)iv, 0, ivlen);
 
1609
                free(iv);
 
1610
        }
 
1611
 
 
1612
        if(listenreply || saref) {
 
1613
                ssize_t readlen;
 
1614
                unsigned char pfkey_buf[PFKEYv2_MAX_MSGSIZE];
 
1615
                
 
1616
                while((readlen = read(pfkey_sock, pfkey_buf, sizeof(pfkey_buf))) > 0) {
 
1617
                        struct sadb_ext *extensions[SADB_EXT_MAX + 1];
 
1618
                        pfkey_extensions_init(extensions);
 
1619
                        pfkey_msg = (struct sadb_msg *)pfkey_buf;
 
1620
                        
 
1621
                        /* first, see if we got enough for an sadb_msg */
 
1622
                        if((size_t)readlen < sizeof(struct sadb_msg)) {
 
1623
                                if(debug) {
 
1624
                                        printf("%s: runt packet of size: %ld (<%lu)\n",
 
1625
                                               program_name, (long)readlen, (unsigned long)sizeof(struct sadb_msg));
 
1626
                                }
 
1627
                                continue;
 
1628
                        }
 
1629
                        
 
1630
                        /* okay, we got enough for a message, print it out */
 
1631
                        if(debug) {
 
1632
                                printf("%s: pfkey v%d msg received. type=%d(%s) seq=%d len=%d pid=%d errno=%d satype=%d(%s)\n",
 
1633
                                       program_name,
 
1634
                                       pfkey_msg->sadb_msg_version,
 
1635
                                       pfkey_msg->sadb_msg_type,
 
1636
                                       pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
 
1637
                                       pfkey_msg->sadb_msg_seq,
 
1638
                                       pfkey_msg->sadb_msg_len,
 
1639
                                       pfkey_msg->sadb_msg_pid,
 
1640
                                       pfkey_msg->sadb_msg_errno,
 
1641
                                       pfkey_msg->sadb_msg_satype,
 
1642
                                       satype2name(pfkey_msg->sadb_msg_satype));
 
1643
                        }
 
1644
                        
 
1645
                        if(readlen != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN))
 
1646
                        {
 
1647
                                if(debug) {
 
1648
                                        printf("%s: packet size read from socket=%d doesn't equal sadb_msg_len %u * %u; message not decoded\n",
 
1649
                                               program_name,
 
1650
                                               (int)readlen, 
 
1651
                                               (unsigned)pfkey_msg->sadb_msg_len,
 
1652
                                               (unsigned)IPSEC_PFKEYv2_ALIGN);
 
1653
                                }
 
1654
                                continue;
 
1655
                        }
 
1656
                        
 
1657
                        if (pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_OUT)) {
 
1658
                                if(debug) {
 
1659
                                        printf("%s: unparseable PF_KEY message.\n",
 
1660
                                               program_name);
 
1661
                                }
 
1662
                                continue;
 
1663
                        } else {
 
1664
                                if(debug) {
 
1665
                                        printf("%s: parseable PF_KEY message.\n",
 
1666
                                               program_name);
 
1667
                                }
 
1668
                        }
 
1669
                        if((pid_t)pfkey_msg->sadb_msg_pid == mypid) {
 
1670
                                if(saref) {
 
1671
                                        printf("%s: saref=%d\n",
 
1672
                                               program_name,
 
1673
                                               (extensions[SADB_EXT_SA] != NULL)
 
1674
                                               ? ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_x_sa_ref
 
1675
                                               : IPSEC_SAREF_NULL);
 
1676
                                }
 
1677
                                break;
 
1678
                        }
 
1679
                }
 
1680
        }
 
1681
        (void) close(pfkey_sock);  /* close the socket */
 
1682
        if(debug || listenreply) {
 
1683
                printf("%s: exited normally\n", program_name);
 
1684
        }
 
1685
        exit(0);
 
1686
}
 
1687
 
 
1688
/*
 
1689
 * $Log: algoinfo.c,v $
 
1690
 * Revision 1.1  2004/04/29 04:13:02  mcr
 
1691
 *      diagnostic program for algorithm code.
 
1692
 *
 
1693
 * Revision 1.105  2004/04/26 05:05:04  ken
 
1694
 * Cast properly on 64bit platforms
 
1695
 *
 
1696
 * Revision 1.104  2004/04/18 03:08:02  mcr
 
1697
 *      use common files from libopenswan.
 
1698
 *
 
1699
 * Revision 1.103  2004/04/06 03:04:54  mcr
 
1700
 *      pullup of algo code from alg-branch.
 
1701
 *
 
1702
 * Revision 1.102  2004/04/04 01:53:13  ken
 
1703
 * Use openswan includes
 
1704
 *
 
1705
 * Revision 1.101.4.2  2004/04/06 00:53:06  mcr
 
1706
 *      code adjusted to compile on branch
 
1707
 *
 
1708
 * Revision 1.101.4.1  2003/12/22 15:25:53  jjo
 
1709
 *      Merged algo-0.8.1-rc11-test1 into alg-branch
 
1710
 *
 
1711
 * Revision 1.101  2003/12/05 16:44:19  mcr
 
1712
 *      patches to avoid ipsec_netlink.h, which has been obsolete for
 
1713
 *      some time now.
 
1714
 *
 
1715
 * Revision 1.100  2003/09/10 00:01:38  mcr
 
1716
 *      fixes for gcc 3.3 from Matthias Bethke <Matthias.Bethke@gmx.net>
 
1717
 *
 
1718
 * Revision 1.99  2003/06/07 16:42:10  dhr
 
1719
 *
 
1720
 * adjust spi.c to conform to stronger type checking of GCC 3.3
 
1721
 *
 
1722
 * Revision 1.98  2003/01/30 02:33:07  rgb
 
1723
 *
 
1724
 * Added ENOSPC for no room in SAref table and ESPIPE for SAref internal error.
 
1725
 *
 
1726
 * Revision 1.97  2002/12/13 18:16:08  mcr
 
1727
 *      restored sa_ref code
 
1728
 *
 
1729
 * Revision 1.96  2002/12/13 18:05:19  mcr
 
1730
 *      temporarily removed sadb_x_sa_ref reference for 2.xx
 
1731
 *
 
1732
 * Revision 1.95  2002/10/09 03:12:05  dhr
 
1733
 *
 
1734
 * [kenb+dhr] 64-bit fixes
 
1735
 *
 
1736
 * Revision 1.94  2002/09/26 15:46:34  dhr
 
1737
 *
 
1738
 * C labels must be on statements.
 
1739
 *
 
1740
 * Revision 1.93  2002/09/20 15:41:24  rgb
 
1741
 * Added --saref option to print out saref returned by pfkey.
 
1742
 * Fixed argcount bug introduced by --listenreply option.
 
1743
 *
 
1744
 * Revision 1.92  2002/09/20 05:02:21  rgb
 
1745
 * Updated copyright date.
 
1746
 * Cruft clean-out.
 
1747
 * Cleaned up pfkey_lib_debug usage.
 
1748
 * Added program_name to beginning of all output for consistency.
 
1749
 *
 
1750
 * Revision 1.91  2002/09/11 20:29:40  mcr
 
1751
 *      turn off automatic printing of reply unless --listenreply
 
1752
 *      is added.
 
1753
 *
 
1754
 * Revision 1.90  2002/09/11 18:48:26  mcr
 
1755
 *      have spi program read from the pfkey socket until it sees
 
1756
 *      a message with its own PID, then exit.
 
1757
 *
 
1758
 * Revision 1.89  2002/07/24 18:44:54  rgb
 
1759
 * Type fiddling to tame ia64 compiler.
 
1760
 *
 
1761
 * Revision 1.88  2002/07/23 02:58:58  rgb
 
1762
 * Fixed "opening" speeling mistake.
 
1763
 *
 
1764
 * Revision 1.87  2002/05/23 07:14:11  rgb
 
1765
 * Cleaned up %p variants to 0p%p for test suite cleanup.
 
1766
 *
 
1767
 * Revision 1.86  2002/04/24 07:55:32  mcr
 
1768
 *      #include patches and Makefiles for post-reorg compilation.
 
1769
 *
 
1770
 * Revision 1.85  2002/04/24 07:35:40  mcr
 
1771
 * Moved from ./klips/utils/spi.c,v
 
1772
 *
 
1773
 * Revision 1.84  2002/03/08 21:44:04  rgb
 
1774
 * Update for all GNU-compliant --version strings.
 
1775
 *
 
1776
 * Revision 1.83  2002/02/20 00:01:53  rgb
 
1777
 * Cleaned out unused code.
 
1778
 *
 
1779
 * Revision 1.82  2001/11/09 02:16:37  rgb
 
1780
 * Fixed bug that erroneously required explicit af parameter for --said.
 
1781
 * Fixed missing SA message on delete.
 
1782
 *
 
1783
 * Revision 1.81  2001/11/06 20:18:47  rgb
 
1784
 * Added lifetime parameters.
 
1785
 *
 
1786
 * Revision 1.80  2001/10/25 06:57:10  rgb
 
1787
 * Added space as legal delimiter in lifetime parameter list.
 
1788
 *
 
1789
 * Revision 1.79  2001/10/24 03:23:55  rgb
 
1790
 * Moved lifetime option parsing to a seperate function and allowed for
 
1791
 * comma-seperated lists of lifetime parameters.
 
1792
 * Moved SATYPE registrations to a seperate function.
 
1793
 *
 
1794
 * Revision 1.78  2001/10/22 19:49:35  rgb
 
1795
 * Added lifetime parameter capabilities.
 
1796
 *
 
1797
 * Revision 1.77  2001/10/02 17:17:17  rgb
 
1798
 * Check error return for all "tto*" calls and report errors.  This, in
 
1799
 * conjuction with the fix to "tto*" will detect AF not set.
 
1800
 *
 
1801
 * Revision 1.76  2001/09/08 21:13:35  rgb
 
1802
 * Added pfkey ident extension support for ISAKMPd. (NetCelo)
 
1803
 *
 
1804
 * Revision 1.75  2001/09/07 22:24:42  rgb
 
1805
 * Added EAFNOSUPPORT socket open error code in case KLIPS is not loaded.
 
1806
 *
 
1807
 * Revision 1.74  2001/06/14 19:35:14  rgb
 
1808
 * Update copyright date.
 
1809
 *
 
1810
 * Revision 1.73  2001/05/30 08:14:05  rgb
 
1811
 * Removed vestiges of esp-null transforms.
 
1812
 *
 
1813
 * Revision 1.72  2001/05/21 02:02:55  rgb
 
1814
 * Eliminate 1-letter options.
 
1815
 *
 
1816
 * Revision 1.71  2001/05/16 05:07:20  rgb
 
1817
 * Fixed --label option in KLIPS manual utils to add the label to the
 
1818
 * command name rather than replace it in error text.
 
1819
 * Fix 'print table' non-option in KLIPS manual utils to deal with --label
 
1820
 * and --debug options.
 
1821
 *
 
1822
 * Revision 1.70  2000/11/06 04:36:57  rgb
 
1823
 * Display conversion on replay_window failure.
 
1824
 * Don't register SATYPEs for manual.
 
1825
 *
 
1826
 * Revision 1.69  2000/09/28 00:37:20  rgb
 
1827
 * Swapped order of pfkey_registration of IPCOMP and IPIP.
 
1828
 *
 
1829
 * Revision 1.68  2000/09/17 18:56:48  rgb
 
1830
 * Added IPCOMP support.
 
1831
 *
 
1832
 * Revision 1.67  2000/09/12 22:36:45  rgb
 
1833
 * Gerhard's IPv6 support.
 
1834
 *
 
1835
 * Revision 1.66  2000/09/08 19:17:31  rgb
 
1836
 * Removed all references to CONFIG_IPSEC_PFKEYv2.
 
1837
 *
 
1838
 * Revision 1.65  2000/08/30 05:34:54  rgb
 
1839
 * Minor clean-up.
 
1840
 *
 
1841
 * Revision 1.64  2000/08/27 01:50:51  rgb
 
1842
 * Update copyright dates and fix replay window endian bug.
 
1843
 *
 
1844
 * Revision 1.63  2000/08/18 21:19:27  rgb
 
1845
 * Removed no longer used resolve_ip() code.
 
1846
 *
 
1847
 * Revision 1.62  2000/08/01 14:51:53  rgb
 
1848
 * Removed _all_ remaining traces of DES.
 
1849
 *
 
1850
 * Revision 1.61  2000/07/26 20:48:42  rgb
 
1851
 * Fixed typo that caused compile failure.
 
1852
 *
 
1853
 * Revision 1.60  2000/07/26 03:41:46  rgb
 
1854
 * Changed all printf's to fprintf's.  Fixed tncfg's usage to stderr.
 
1855
 *
 
1856
 * Revision 1.59  2000/06/21 16:51:27  rgb
 
1857
 * Added no additional argument option to usage text.
 
1858
 *
 
1859
 * Revision 1.58  2000/03/16 06:40:49  rgb
 
1860
 * Hardcode PF_KEYv2 support.
 
1861
 *
 
1862
 * Revision 1.57  2000/01/22 23:22:46  rgb
 
1863
 * Use new function proto2satype().
 
1864
 *
 
1865
 * Revision 1.56  2000/01/21 09:42:32  rgb
 
1866
 * Replace resolve_ip() with atoaddr() from freeswanlib.
 
1867
 *
 
1868
 * Revision 1.55  2000/01/21 06:24:57  rgb
 
1869
 * Blasted any references in usage and code to deleted algos.
 
1870
 * Removed DES usage.
 
1871
 * Changed usage of memset on extensions to pfkey_extensions_init().
 
1872
 *
 
1873
 *
 
1874
 */