3 * Copyright © 2006-2008 Daniele Lacamera
4 * from an idea by Renzo Davoli
6 * Released under the terms of GNU GPL v.2
7 * (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
8 * with the additional exemption that
9 * compiling, linking, and/or using OpenSSL is allowed.
18 static void Usage(char *programname
)
21 fprintf(stderr
,"Usage: %s [-s socketname] [-c [remoteuser@]remotehost[:remoteport]] [-p localport] [-P pre-shared/key/path] [-d] [-x] [-v]\n",programname
);
25 static EVP_CIPHER_CTX ctx
;
26 static int ctx_initialized
= 0;
27 static int encryption_disabled
= 0;
29 static unsigned long long mycounter
=1;
30 static struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
31 static int verbose
= 0;
33 void vc_printlog(int priority
, const char *format
, ...)
36 if(verbose
>= priority
){
37 va_start (arg
, format
);
39 fprintf(stderr
,"vde_cryptcab: ");
40 vfprintf(stderr
,format
,arg
);
46 void disable_encryption(void) {
47 encryption_disabled
= 1;
48 vc_printlog(3,"Encryption Disabled.");
56 * Check progressive number validity in incoming datagram
59 isvalid_timestamp(unsigned char *block
, int size
, struct peer
*p
)
64 unsigned long long pktcounter
=0;
66 pktcounter
+=block
[size
-12+i
]<<(i
*8);
68 if(pktcounter
>p
->counter
){
69 p
->counter
=pktcounter
;
72 //fprintf(stderr,"bad timestamp!\n");
79 * Check CRC32 Checksum from incoming datagram
82 isvalid_crc32(unsigned char *block
, int len
)
84 unsigned char *crc
=(unsigned char *)crc32(block
,len
-4);
85 if(strncmp((char*)block
+(len
-4),(char*)crc
,4)==0){
90 //fprintf(stderr,"bad crc32!\n");
96 int data_encrypt(unsigned char *src
, unsigned char *dst
, int len
, struct peer
*p
)
100 if (encryption_disabled
){
105 if (!ctx_initialized
) {
106 EVP_CIPHER_CTX_init (&ctx
);
110 EVP_EncryptInit (&ctx
, EVP_bf_cbc (), p
->key
, p
->iv
);
111 if (EVP_EncryptUpdate (&ctx
, dst
, &olen
, src
, len
) != 1)
113 fprintf (stderr
,"error in encrypt update\n");
118 if (EVP_EncryptFinal (&ctx
, dst
+ olen
, &tlen
) != 1)
120 fprintf (stderr
,"error in encrypt final\n");
127 EVP_CIPHER_CTX_cleanup(&ctx
);
131 int data_decrypt(unsigned char *src
, unsigned char *dst
, int len
, struct peer
*p
)
135 if (encryption_disabled
){
140 if (!ctx_initialized
) {
141 EVP_CIPHER_CTX_init (&ctx
);
145 EVP_DecryptInit (&ctx
, EVP_bf_cbc (), p
->key
, p
->iv
);
146 if (EVP_DecryptUpdate (&ctx
, dst
, &olen
, src
, len
) != 1)
148 fprintf (stderr
,"error in decrypt update\n");
153 if (EVP_DecryptFinal (&ctx
, dst
+ olen
, &tlen
) != 1)
155 fprintf (stderr
,"error in decrypt final\n");
162 EVP_CIPHER_CTX_cleanup(&ctx
);
167 * Include a progressive number into outgoing datagram,
168 * to prevent packet replication/injection attack.
172 set_timestamp(unsigned char *block
)
176 block
[i
]=(unsigned char)(mycounter
>>(i
*8))&(0x00000000000000FF);
185 * Send an udp datagram to specified peer.
188 send_udp (unsigned char *data
, size_t len
, struct peer
*p
, unsigned char flags
)
191 unsigned char outpkt
[MAXPKT
];
192 unsigned char *outbuf
=outpkt
+1;
194 struct sockaddr_in
*destination
=&(p
->in_a
);
196 if (encryption_disabled
|| (flags
==CMD_CHALLENGE
|| flags
==CMD_LOGIN
|| flags
==CMD_DENY
|| flags
==CMD_AUTH_OK
|| flags
== CMD_KEEPALIVE
)){
197 memcpy(outbuf
,data
,len
);
201 set_timestamp(data
+len
);
204 crc
= crc32(data
,len
);
205 memcpy(data
+len
,crc
,4);
210 olen
= data_encrypt(data
,outbuf
,len
,p
);
213 sendto(nfd
, outpkt
, olen
+ 1, 0, (struct sockaddr
*) destination
,
214 sizeof(struct sockaddr_in
));
215 vc_printlog(4,"UDP Sent %dB datagram.",olen
+1);
219 vde_plug(struct peer
*p
, char *plugname
)
221 p
->plug
=vde_open(plugname
,"vde_cryptcab",&open_args
);
224 perror ("libvdeplug");
227 vc_printlog(3,"Socket to local switch created: fd=%d",vde_datafd(p
->plug
));
231 * Send a virtual frame to the vde_plug process associated
235 send_vdeplug(const char *data
, size_t len
, struct peer
*p
)
237 static unsigned int outbuf
[MAXPKT
];
239 static u_int16_t outlen
;
243 if(outp
==0 && (len
>=2) ){
245 outlen
+=(unsigned char)data
[1];
246 outlen
+=((unsigned char)(data
[0]))<<8;
250 vde_send(p
->plug
,data
,outlen
,0);
251 send_vdeplug(data
+outlen
,len
-outlen
, p
);
255 memcpy(outbuf
+outp
,data
,len
);
258 vde_send(p
->plug
,(char *)outbuf
,outlen
,0);
260 vc_printlog(3,"VDE - Sent a %dB datagram.",outlen
);
266 int main(int argc
, char **argv
, char **env
)
269 char *programname
=argv
[0];
270 char *plugname
="/tmp/vde.ctl";
271 char *remotehost
= NULL
;
272 char *remoteusr
= NULL
;
273 char *pre_shared
= NULL
;
274 enum e_enc_type enc_type
= ENC_SSH
;
275 unsigned short udp_port
= PORTNO
;
276 unsigned short remoteport
= PORTNO
;
277 unsigned char keepalives
=0;
278 char *scp_extra_options
;
281 scp_extra_options
=getenv("SCP_EXTRA_OPTIONS");
285 int option_index
= 0;
287 const char sepusr
='@';
288 const char sepport
=':';
289 char *pusr
,*pport
, *vvv
=NULL
;
291 static struct option long_options
[] = {
293 {"vdesock", 1, 0, 's'},
295 {"localport", 1, 0, 'p'},
297 {"preshared ",1,0,'P'},
298 {"noencrypt",0,0,'x'},
299 {"keepalive",0,0,'k'},
300 {"verbose",optional_argument
,0,'v'},
305 c
= GETOPT_LONG (argc
, argv
, "s:p:c:P:hv::xkd",
306 long_options
, &option_index
);
311 plugname
=strdup(optarg
);
317 while(vvv
&& *vvv
++ == 'v')
321 enc_type
= ENC_NOENC
;
324 ctl_socket
=strdup(optarg
);
326 pusr
=strchr(ctl_socket
,sepusr
);
327 pport
=strchr(ctl_socket
,sepport
);
329 if( ( pusr
!= strrchr(ctl_socket
,sepusr
)) ||
330 (pport
!= strrchr(ctl_socket
,sepport
)) ||
331 (pport
&& pusr
>pport
) )
337 remotehost
=strdup(ctl_socket
);
341 remoteusr
=(char *)strndup(ctl_socket
,pusr
-ctl_socket
);
342 remotehost
=(char *)strndup(pusr
+1,strlen(ctl_socket
)-strlen(remoteusr
)-1);
348 remotehost
=(char *)strndup(ctl_socket
,pport
-ctl_socket
);
349 remoteport
=atoi((char *)strndup(pport
+1,strlen(ctl_socket
)-strlen(remotehost
)-1));
352 remoteusr
=(char *)strndup(ctl_socket
,pusr
-ctl_socket
);
353 remotehost
=(char *)strndup(pusr
+1,pport
-pusr
-1);
354 remoteport
=atoi((char *)strndup(pport
+1,strlen(ctl_socket
)-strlen(remotehost
)-strlen(remoteusr
)-2));
358 udp_port
=atoi(optarg
);
362 pre_shared
=strdup(optarg
);
363 fprintf(stderr
,"Using pre-shared key %s\n",pre_shared
);
364 enc_type
= ENC_PRESHARED
;
380 if (keepalives
&& remotehost
==NULL
){
381 fprintf(stderr
,"\nkeepalive option is valid in client mode only.\n\n");
384 if (pre_shared
&& enc_type
== ENC_NOENC
){
385 fprintf(stderr
,"\nWarning: Not using pre-shared key mode, encryption disabled.\n\n");
390 vc_printlog(1,"Verbosity: %d", verbose
);
391 chksum_crc32gentab();
395 vc_printlog(1,"Encryption Disabled.");
398 vc_printlog(1,"Using pre-shared key %s",pre_shared
);
401 vc_printlog(1,"Using ssh key exchange for authentication");
409 close(STDOUT_FILENO
);
416 cryptcab_server(plugname
, udp_port
, enc_type
, pre_shared
);
418 cryptcab_client(plugname
, udp_port
, enc_type
, pre_shared
, remoteusr
, remotehost
, remoteport
, keepalives
, scp_extra_options
);