| /* $NetBSD: localconf.c,v 1.7 2008/12/23 14:04:42 tteras Exp $ */ |
| |
| /* $KAME: localconf.c,v 1.33 2001/08/09 07:32:19 sakane Exp $ */ |
| |
| /* |
| * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the project nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| |
| #include <sys/types.h> |
| #include <sys/param.h> |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <ctype.h> |
| #include <err.h> |
| |
| #include "var.h" |
| #include "misc.h" |
| #include "vmbuf.h" |
| #include "plog.h" |
| #include "debug.h" |
| |
| #include "localconf.h" |
| #include "algorithm.h" |
| #include "admin.h" |
| #include "privsep.h" |
| #include "isakmp_var.h" |
| #include "isakmp.h" |
| #include "ipsec_doi.h" |
| #include "grabmyaddr.h" |
| #include "vendorid.h" |
| #include "str2val.h" |
| #include "safefile.h" |
| #include "admin.h" |
| #include "gcmalloc.h" |
| |
| struct localconf *lcconf; |
| |
| static void setdefault __P((void)); |
| |
| void |
| initlcconf() |
| { |
| lcconf = racoon_calloc(1, sizeof(*lcconf)); |
| if (lcconf == NULL) |
| errx(1, "failed to allocate local conf."); |
| |
| setdefault(); |
| |
| lcconf->racoon_conf = LC_DEFAULT_CF; |
| } |
| |
| void |
| flushlcconf() |
| { |
| int i; |
| |
| setdefault(); |
| myaddr_flush(); |
| |
| for (i = 0; i < LC_PATHTYPE_MAX; i++) { |
| if (lcconf->pathinfo[i]) { |
| racoon_free(lcconf->pathinfo[i]); |
| lcconf->pathinfo[i] = NULL; |
| } |
| } |
| } |
| |
| static void |
| setdefault() |
| { |
| lcconf->uid = 0; |
| lcconf->gid = 0; |
| lcconf->chroot = NULL; |
| lcconf->port_isakmp = PORT_ISAKMP; |
| lcconf->port_isakmp_natt = PORT_ISAKMP_NATT; |
| lcconf->default_af = AF_INET; |
| lcconf->pad_random = LC_DEFAULT_PAD_RANDOM; |
| lcconf->pad_randomlen = LC_DEFAULT_PAD_RANDOMLEN; |
| lcconf->pad_maxsize = LC_DEFAULT_PAD_MAXSIZE; |
| lcconf->pad_strict = LC_DEFAULT_PAD_STRICT; |
| lcconf->pad_excltail = LC_DEFAULT_PAD_EXCLTAIL; |
| lcconf->retry_counter = LC_DEFAULT_RETRY_COUNTER; |
| lcconf->retry_interval = LC_DEFAULT_RETRY_INTERVAL; |
| lcconf->count_persend = LC_DEFAULT_COUNT_PERSEND; |
| lcconf->secret_size = LC_DEFAULT_SECRETSIZE; |
| lcconf->retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1; |
| lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE; |
| lcconf->strict_address = FALSE; |
| lcconf->complex_bundle = TRUE; /*XXX FALSE;*/ |
| lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */ |
| lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL; |
| lcconf->pfkey_buffer_size = LC_DEFAULT_PFKEY_BUFFER_SIZE; |
| } |
| |
| /* |
| * get PSK by string. |
| */ |
| vchar_t * |
| getpskbyname(id0) |
| vchar_t *id0; |
| { |
| char *id; |
| vchar_t *key = NULL; |
| |
| id = racoon_calloc(1, 1 + id0->l - sizeof(struct ipsecdoi_id_b)); |
| if (id == NULL) { |
| plog(LLV_ERROR, LOCATION, NULL, |
| "failed to get psk buffer.\n"); |
| goto end; |
| } |
| memcpy(id, id0->v + sizeof(struct ipsecdoi_id_b), |
| id0->l - sizeof(struct ipsecdoi_id_b)); |
| id[id0->l - sizeof(struct ipsecdoi_id_b)] = '\0'; |
| |
| key = privsep_getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b)); |
| |
| end: |
| if (id) |
| racoon_free(id); |
| return key; |
| } |
| |
| /* |
| * get PSK by address. |
| */ |
| vchar_t * |
| getpskbyaddr(remote) |
| struct sockaddr *remote; |
| { |
| vchar_t *key = NULL; |
| char addr[NI_MAXHOST], port[NI_MAXSERV]; |
| |
| GETNAMEINFO(remote, addr, port); |
| |
| key = privsep_getpsk(addr, strlen(addr)); |
| |
| return key; |
| } |
| |
| vchar_t * |
| getpsk(str, len) |
| const char *str; |
| const int len; |
| { |
| FILE *fp; |
| char buf[1024]; /* XXX how is variable length ? */ |
| vchar_t *key = NULL; |
| char *p, *q; |
| size_t keylen; |
| char *k = NULL; |
| |
| if (safefile(lcconf->pathinfo[LC_PATHTYPE_PSK], 1) == 0) |
| fp = fopen(lcconf->pathinfo[LC_PATHTYPE_PSK], "r"); |
| else |
| fp = NULL; |
| if (fp == NULL) { |
| plog(LLV_ERROR, LOCATION, NULL, |
| "failed to open pre_share_key file %s\n", |
| lcconf->pathinfo[LC_PATHTYPE_PSK]); |
| return NULL; |
| } |
| |
| while (fgets(buf, sizeof(buf), fp) != NULL) { |
| /* comment line */ |
| if (buf[0] == '#') |
| continue; |
| |
| /* search the end of 1st string. */ |
| for (p = buf; *p != '\0' && !isspace((int)*p); p++) |
| ; |
| if (*p == '\0') |
| continue; /* no 2nd parameter */ |
| *p = '\0'; |
| /* search the 1st of 2nd string. */ |
| while (isspace((int)*++p)) |
| ; |
| if (*p == '\0') |
| continue; /* no 2nd parameter */ |
| p--; |
| if (strncmp(buf, str, len) == 0 && buf[len] == '\0') { |
| p++; |
| keylen = 0; |
| for (q = p; *q != '\0' && *q != '\n'; q++) |
| keylen++; |
| *q = '\0'; |
| |
| /* fix key if hex string */ |
| if (strncmp(p, "0x", 2) == 0) { |
| k = str2val(p + 2, 16, &keylen); |
| if (k == NULL) { |
| plog(LLV_ERROR, LOCATION, NULL, |
| "failed to get psk buffer.\n"); |
| goto end; |
| } |
| p = k; |
| } |
| |
| key = vmalloc(keylen); |
| if (key == NULL) { |
| plog(LLV_ERROR, LOCATION, NULL, |
| "failed to allocate key buffer.\n"); |
| goto end; |
| } |
| memcpy(key->v, p, key->l); |
| if (k) |
| racoon_free(k); |
| goto end; |
| } |
| } |
| |
| end: |
| fclose(fp); |
| return key; |
| } |
| |
| /* |
| * get a file name of a type specified. |
| */ |
| void |
| getpathname(path, len, type, name) |
| char *path; |
| int len, type; |
| const char *name; |
| { |
| snprintf(path, len, "%s%s%s", |
| name[0] == '/' ? "" : lcconf->pathinfo[type], |
| name[0] == '/' ? "" : "/", |
| name); |
| |
| plog(LLV_DEBUG, LOCATION, NULL, "filename: %s\n", path); |
| } |
| |
| #if 0 /* DELETEIT */ |
| static int lc_doi2idtype[] = { |
| -1, |
| -1, |
| LC_IDENTTYPE_FQDN, |
| LC_IDENTTYPE_USERFQDN, |
| -1, |
| -1, |
| -1, |
| -1, |
| -1, |
| LC_IDENTTYPE_CERTNAME, |
| -1, |
| LC_IDENTTYPE_KEYID, |
| }; |
| |
| /* |
| * convert DOI value to idtype |
| * OUT -1 : NG |
| * other: converted. |
| */ |
| int |
| doi2idtype(idtype) |
| int idtype; |
| { |
| if (ARRAYLEN(lc_doi2idtype) > idtype) |
| return lc_doi2idtype[idtype]; |
| return -1; |
| } |
| #endif |
| |
| static int lc_sittype2doi[] = { |
| IPSECDOI_SIT_IDENTITY_ONLY, |
| IPSECDOI_SIT_SECRECY, |
| IPSECDOI_SIT_INTEGRITY, |
| }; |
| |
| /* |
| * convert sittype to DOI value. |
| * OUT -1 : NG |
| * other: converted. |
| */ |
| int |
| sittype2doi(sittype) |
| int sittype; |
| { |
| if (ARRAYLEN(lc_sittype2doi) > sittype) |
| return lc_sittype2doi[sittype]; |
| return -1; |
| } |
| |
| static int lc_doitype2doi[] = { |
| IPSEC_DOI, |
| }; |
| |
| /* |
| * convert doitype to DOI value. |
| * OUT -1 : NG |
| * other: converted. |
| */ |
| int |
| doitype2doi(doitype) |
| int doitype; |
| { |
| if (ARRAYLEN(lc_doitype2doi) > doitype) |
| return lc_doitype2doi[doitype]; |
| return -1; |
| } |
| |
| |
| |
| static void |
| saverestore_params(f) |
| int f; |
| { |
| static u_int16_t s_port_isakmp; |
| |
| /* 0: save, 1: restore */ |
| if (f) { |
| lcconf->port_isakmp = s_port_isakmp; |
| } else { |
| s_port_isakmp = lcconf->port_isakmp; |
| } |
| } |
| |
| void |
| restore_params() |
| { |
| saverestore_params(1); |
| } |
| |
| void |
| save_params() |
| { |
| saverestore_params(0); |
| } |