|
|
1.1 misho 1: /*
2: * Copyright (C) 2012 Reto Guadagnini
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "ipseckey.h"
17:
18: #include <library.h>
19: #include <utils/debug.h>
20: #include <bio/bio_reader.h>
21:
22: typedef struct private_ipseckey_t private_ipseckey_t;
23:
24: /**
25: * private data of the ipseckey
26: */
27: struct private_ipseckey_t {
28:
29: /**
30: * public functions
31: */
32: ipseckey_t public;
33:
34: /**
35: * Precedence
36: */
37: uint8_t precedence;
38:
39: /**
40: * Gateway type
41: */
42: uint8_t gateway_type;
43:
44: /**
45: * Algorithm
46: */
47: uint8_t algorithm;
48:
49: /**
50: * Gateway
51: */
52: chunk_t gateway;
53:
54: /**
55: * Public key
56: */
57: chunk_t public_key;
58: };
59:
60: METHOD(ipseckey_t, get_precedence, uint8_t,
61: private_ipseckey_t *this)
62: {
63: return this->precedence;
64: }
65:
66: METHOD(ipseckey_t, get_gateway_type, ipseckey_gw_type_t,
67: private_ipseckey_t *this)
68: {
69: return this->gateway_type;
70: }
71:
72: METHOD(ipseckey_t, get_algorithm, ipseckey_algorithm_t,
73: private_ipseckey_t *this)
74: {
75: return this->algorithm;
76: }
77:
78: METHOD(ipseckey_t, get_gateway, chunk_t,
79: private_ipseckey_t *this)
80: {
81: return this->gateway;
82: }
83:
84: METHOD(ipseckey_t, get_public_key, chunk_t,
85: private_ipseckey_t *this)
86: {
87: return this->public_key;
88: }
89:
90: METHOD(ipseckey_t, destroy, void,
91: private_ipseckey_t *this)
92: {
93: chunk_free(&this->gateway);
94: chunk_free(&this->public_key);
95: free(this);
96: }
97:
98: /*
99: * See header
100: */
101: ipseckey_t *ipseckey_create_frm_rr(rr_t *rr)
102: {
103: private_ipseckey_t *this;
104: bio_reader_t *reader = NULL;
105: uint8_t label;
106: chunk_t tmp;
107:
108: INIT(this,
109: .public = {
110: .get_precedence = _get_precedence,
111: .get_gateway_type = _get_gateway_type,
112: .get_algorithm = _get_algorithm,
113: .get_gateway = _get_gateway,
114: .get_public_key = _get_public_key,
115: .destroy = _destroy,
116: },
117: );
118:
119: if (rr->get_type(rr) != RR_TYPE_IPSECKEY)
120: {
121: DBG1(DBG_CFG, "unable to create an ipseckey out of an RR "
122: "whose type is not IPSECKEY");
123: free(this);
124: return NULL;
125: }
126:
127: /** Parse the content (RDATA field) of the RR */
128: reader = bio_reader_create(rr->get_rdata(rr));
129: if (!reader->read_uint8(reader, &this->precedence) ||
130: !reader->read_uint8(reader, &this->gateway_type) ||
131: !reader->read_uint8(reader, &this->algorithm))
132: {
133: DBG1(DBG_CFG, "ipseckey RR has a wrong format");
134: reader->destroy(reader);
135: free(this);
136: return NULL;
137: }
138:
139: switch (this->gateway_type)
140: {
141: case IPSECKEY_GW_TP_NOT_PRESENT:
142: break;
143:
144: case IPSECKEY_GW_TP_IPV4:
145: if (!reader->read_data(reader, 4, &this->gateway))
146: {
147: DBG1(DBG_CFG, "ipseckey gateway field does not contain an "
148: "IPv4 address as expected");
149: reader->destroy(reader);
150: free(this);
151: return NULL;
152: }
153: this->gateway = chunk_clone(this->gateway);
154: break;
155:
156: case IPSECKEY_GW_TP_IPV6:
157: if (!reader->read_data(reader, 16, &this->gateway))
158: {
159: DBG1(DBG_CFG, "ipseckey gateway field does not contain an "
160: "IPv6 address as expected");
161: reader->destroy(reader);
162: free(this);
163: return NULL;
164: }
165: this->gateway = chunk_clone(this->gateway);
166: break;
167:
168: case IPSECKEY_GW_TP_WR_ENC_DNAME:
169: /**
170: * Uncompressed domain name as defined in RFC 1035 chapter 3.
171: *
172: * TODO: Currently we ignore wire encoded domain names.
173: *
174: */
175: while (reader->read_uint8(reader, &label) &&
176: label != 0 && label < 192)
177: {
178: if (!reader->read_data(reader, label, &tmp))
179: {
180: DBG1(DBG_CFG, "wrong wire encoded domain name format "
181: "in ipseckey gateway field");
182: reader->destroy(reader);
183: free(this);
184: return NULL;
185: }
186: }
187: break;
188:
189: default:
190: DBG1(DBG_CFG, "unable to parse ipseckey gateway field");
191: reader->destroy(reader);
192: free(this);
193: return NULL;
194: }
195:
196: if (!reader->read_data(reader, reader->remaining(reader),
197: &this->public_key))
198: {
199: DBG1(DBG_CFG, "failed to read ipseckey public key field");
200: reader->destroy(reader);
201: chunk_free(&this->gateway);
202: free(this);
203: return NULL;
204: }
205: this->public_key = chunk_clone(this->public_key);
206: reader->destroy(reader);
207: return &this->public;
208: }
209: