1 /*
2  * fiked - a fake IKE PSK+XAUTH daemon based on vpnc
3  * Copyright (C) 2005, Daniel Roethlisberger <daniel@roe.ch>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, see http://www.gnu.org/copyleft/
17  *
18  * $Id: peer_ctx.c 103 2005-12-18 16:28:08Z roe $
19  */
20 
21 #include "peer_ctx.h"
22 #include "mem.h"
23 #include "vpnc/math_group.h"
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <stdio.h>
31 
32 /* message_iv */
33 
message_iv_get(uint32_t id,message_iv ** head)34 message_iv * message_iv_get(uint32_t id, message_iv **head)
35 {
36 	message_iv *found = NULL;
37 	for(message_iv *p = *head; p && !found; p = p->next) {
38 		if(p->id == id)
39 			found = p;
40 	}
41 
42 	if(!found) {
43 		mem_allocate(&found, sizeof(message_iv));
44 		memset(found, 0, sizeof(message_iv));
45 		found->id = id;
46 		found->next = *head;
47 		*head = found;
48 	}
49 
50 	return found;
51 }
52 
message_iv_free(message_iv * msg_iv)53 void message_iv_free(message_iv *msg_iv)
54 {
55 	if(msg_iv->next) {
56 		message_iv_free(msg_iv->next);
57 		msg_iv->next = NULL;
58 	}
59 	mem_free(&msg_iv->iv);
60 	free(msg_iv);
61 }
62 
63 
64 /* peer_ctx */
65 
peer_ctx_get(datagram * dgm,config * cfg,peer_ctx ** head)66 peer_ctx * peer_ctx_get(datagram *dgm, config *cfg, peer_ctx **head)
67 {
68 	peer_ctx *found = NULL;
69 	for(peer_ctx *p = *head; p && !found; p = p->next) {
70 		if(p->peer_addr.sin_addr.s_addr == dgm->peer_addr.sin_addr.s_addr &&
71 			p->peer_addr.sin_port == dgm->peer_addr.sin_port)
72 			found = p;
73 	}
74 
75 	if(!found) {
76 		mem_allocate(&found, sizeof(peer_ctx));
77 		memset(found, 0, sizeof(peer_ctx));
78 		found->peer_addr = dgm->peer_addr;
79 		found->next = *head;
80 		found->state = STATE_NEW;
81 		found->cfg = cfg;
82 		*head = found;
83 	}
84 
85 	return found;
86 }
87 
peer_ctx_clear(peer_ctx * ctx)88 void peer_ctx_clear(peer_ctx *ctx)
89 {
90 	mem_free(&ctx->ipsec_id);
91 	mem_free(&ctx->ipsec_secret);
92 	mem_free(&ctx->xauth_username);
93 	mem_free(&ctx->xauth_password);
94 
95 	mem_free(&ctx->key);
96 	mem_free(&ctx->iv0);
97 	if(ctx->msg_iv) {
98 		message_iv_free(ctx->msg_iv);
99 		ctx->msg_iv = NULL;
100 	}
101 
102 	if(ctx->dh_group) {
103 		group_free(ctx->dh_group);
104 		ctx->dh_group = NULL;
105 	}
106 
107 	mem_free(&ctx->dh_i_public);
108 	mem_free(&ctx->dh_r_public);
109 	mem_free(&ctx->dh_secret);
110 
111 	mem_free(&ctx->skeyid);
112 	mem_free(&ctx->skeyid_e);
113 	mem_free(&ctx->skeyid_a);
114 	mem_free(&ctx->skeyid_d);
115 
116 	mem_free(&ctx->i_sa);
117 	mem_free(&ctx->i_id);
118 	mem_free(&ctx->r_id);
119 	mem_free(&ctx->i_nonce);
120 	mem_free(&ctx->r_nonce);
121 	mem_free(&ctx->i_hash);
122 	mem_free(&ctx->r_hash);
123 }
124 
peer_ctx_reset(peer_ctx * ctx)125 void peer_ctx_reset(peer_ctx *ctx)
126 {
127 	peer_ctx_clear(ctx);
128 	memset((uint8_t *)&ctx->state, 0,
129 		(uint8_t *)ctx - (uint8_t *)&ctx->state + sizeof(peer_ctx));
130 	ctx->state = STATE_NEW;
131 }
132 
peer_ctx_free(peer_ctx * ctx)133 void peer_ctx_free(peer_ctx *ctx)
134 {
135 	if(ctx->next) {
136 		peer_ctx_free(ctx->next);
137 		ctx->next = NULL;
138 	}
139 	mem_free(&ctx->last_dgm_hash); /* only free on free_peer_ctx */
140 	peer_ctx_clear(ctx);
141 	free(ctx);
142 }
143