Correctly handle large attributes
[freeradius.git] / src / modules / frs_vmps / vqp.c
1 /*
2  * vqp.c        Functions to send/receive VQP packets.
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2007 Alan DeKok <aland@deployingradius.com>
21  */
22
23 #include        <freeradius-devel/ident.h>
24 RCSID("$Id$");
25
26 #include        <freeradius-devel/radiusd.h>
27 #include        <freeradius-devel/udpfromto.h>
28 #include        "vqp.h"
29
30 #ifdef WITH_VMPS
31
32 #  define debug_pair(vp)        do { if (fr_debug_flag && fr_log_fp) { \
33                                         fputc('\t', fr_log_fp); \
34                                         vp_print(fr_log_fp, vp); \
35                                         fputc('\n', fr_log_fp); \
36                                      } \
37                                 } while(0)
38
39 #define MAX_VMPS_LEN (MAX_STRING_LEN - 1)
40
41 /*
42  *  http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/tcpdump/print-vqp.c
43  *
44  *  Some of how it works:
45  *
46  *  http://www.hackingciscoexposed.com/pdf/chapter12.pdf
47  *
48  * VLAN Query Protocol (VQP)
49  *
50  *    0                   1                   2                   3
51  *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
52  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53  *   |    Version    |    Opcode     | Response Code |  Data Count   |
54  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55  *   |                         Transaction ID                        |
56  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57  *   |                            Type (1)                           |
58  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59  *   |             Length            |            Data               /
60  *   /                                                               /
61  *   /                                                               /
62  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63  *   |                            Type (n)                           |
64  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65  *   |             Length            |            Data               /
66  *   /                                                               /
67  *   /                                                               /
68  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69  *
70  * VQP is layered over UDP.  The default destination port is 1589.
71  *
72  */
73 #define VQP_HDR_LEN (8)
74 #define VQP_VERSION (1)
75 #define VQP_MAX_ATTRIBUTES (12)
76
77
78 /*
79  *      Wrapper for sendto which handles sendfromto, IPv6, and all
80  *      possible combinations.
81  *
82  *      FIXME:  This is just a copy of rad_sendto().
83  *      Duplicate code is bad.
84  */
85 static int vqp_sendto(int sockfd, void *data, size_t data_len, int flags,
86                       fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr,
87                       int dst_port)
88 {
89         struct sockaddr_storage dst;
90         socklen_t               sizeof_dst;
91
92 #ifdef WITH_UDPFROMTO
93         struct sockaddr_storage src;
94         socklen_t               sizeof_src;
95
96         fr_ipaddr2sockaddr(src_ipaddr, 0, &src, &sizeof_src);
97 #else
98         src_ipaddr = src_ipaddr; /* -Wunused */
99 #endif
100
101         if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &dst, &sizeof_dst)) {
102                 return -1;   /* Unknown address family, Die Die Die! */
103         }
104
105 #ifdef WITH_UDPFROMTO
106         /*
107          *      Only IPv4 is supported for udpfromto.
108          *
109          *      And if they don't specify a source IP address, don't
110          *      use udpfromto.
111          */
112         if ((dst_ipaddr->af == AF_INET) ||
113             (src_ipaddr->af != AF_UNSPEC)) {
114                 return sendfromto(sockfd, data, data_len, flags,
115                                   (struct sockaddr *)&src, sizeof_src, 
116                                   (struct sockaddr *)&dst, sizeof_dst);
117         }
118 #else
119         src_ipaddr = src_ipaddr; /* -Wunused */
120 #endif
121
122         /*
123          *      No udpfromto, OR an IPv6 socket, fail gracefully.
124          */
125         return sendto(sockfd, data, data_len, flags, 
126                       (struct sockaddr *)&dst, sizeof_dst);
127 }
128
129 /*
130  *      Wrapper for recvfrom, which handles recvfromto, IPv6, and all
131  *      possible combinations.
132  *
133  *      FIXME:  This is copied from rad_recvfrom, with minor edits.
134  */
135 static ssize_t vqp_recvfrom(int sockfd, uint8_t **pbuf, int flags,
136                             fr_ipaddr_t *src_ipaddr, uint16_t *src_port,
137                             fr_ipaddr_t *dst_ipaddr, uint16_t *dst_port)
138 {
139         struct sockaddr_storage src;
140         struct sockaddr_storage dst;
141         socklen_t               sizeof_src = sizeof(src);
142         socklen_t               sizeof_dst = sizeof(dst);
143         ssize_t                 data_len;
144         uint8_t                 header[4];
145         void                    *buf;
146         size_t                  len;
147         int                     port;
148
149         memset(&src, 0, sizeof_src);
150         memset(&dst, 0, sizeof_dst);
151
152         /*
153          *      Get address family, etc. first, so we know if we
154          *      need to do udpfromto.
155          *
156          *      FIXME: udpfromto also does this, but it's not
157          *      a critical problem.
158          */
159         if (getsockname(sockfd, (struct sockaddr *)&dst,
160                         &sizeof_dst) < 0) return -1;
161
162         /*
163          *      Read the length of the packet, from the packet.
164          *      This lets us allocate the buffer to use for
165          *      reading the rest of the packet.
166          */
167         data_len = recvfrom(sockfd, header, sizeof(header), MSG_PEEK,
168                             (struct sockaddr *)&src, &sizeof_src);
169         if (data_len < 0) return -1;
170
171         /*
172          *      Too little data is available, discard the packet.
173          */
174         if (data_len < 4) {
175                 recvfrom(sockfd, header, sizeof(header), flags, 
176                          (struct sockaddr *)&src, &sizeof_src);
177                 return 0;
178
179                 /*
180                  *      Invalid version, packet type, or too many
181                  *      attributes.  Die.
182                  */
183         } else if ((header[0] != VQP_VERSION) ||
184                    (header[1] < 1) ||
185                    (header[1] > 4) ||
186                    (header[3] > VQP_MAX_ATTRIBUTES)) {
187                 recvfrom(sockfd, header, sizeof(header), flags,
188                          (struct sockaddr *)&src, &sizeof_src);
189                 return 0;
190
191         } else {                /* we got 4 bytes of data. */
192                 /*
193                  *      We don't care about the contents for now...
194                  */
195 #if 0
196                 /*
197                  *      How many attributes are in the packet.
198                  */
199                 len = header[3];
200
201                 if ((header[1] == 1) || (header[1] == 3)) {
202                         if (len != VQP_MAX_ATTRIBUTES) {
203                                 recvfrom(sockfd, header, sizeof(header), 0,
204                                          (struct sockaddr *)&src, &sizeof_src);
205                                 return 0;
206                         }
207                         /*
208                          *      Maximum length we support.
209                          */
210                         len = (12 * (4 + 4 + MAX_VMPS_LEN));
211
212                 } else {
213                         if (len != 2) {
214                                 recvfrom(sockfd, header, sizeof(header), 0, 
215                                  (struct sockaddr *)&src, &sizeof_src);
216                                 return 0;
217                         }
218                         /*
219                          *      Maximum length we support.
220                          */
221                         len = (12 * (4 + 4 + MAX_VMPS_LEN));
222                 }
223 #endif
224         }
225
226         /*
227          *      For now, be generous.
228          */
229         len = (12 * (4 + 4 + MAX_VMPS_LEN));
230
231         buf = malloc(len);
232         if (!buf) return -1;
233
234         /*
235          *      Receive the packet.  The OS will discard any data in the
236          *      packet after "len" bytes.
237          */
238 #ifdef WITH_UDPFROMTO
239         if (dst.ss_family == AF_INET) {
240                 data_len = recvfromto(sockfd, buf, len, flags,
241                                       (struct sockaddr *)&src, &sizeof_src, 
242                                       (struct sockaddr *)&dst, &sizeof_dst);
243         } else
244 #endif
245                 /*
246                  *      No udpfromto, OR an IPv6 socket.  Fail gracefully.
247                  */
248                 data_len = recvfrom(sockfd, buf, len, flags, 
249                                     (struct sockaddr *)&src, &sizeof_src);
250         if (data_len < 0) {
251                 free(buf);
252                 return data_len;
253         }
254
255         if (!fr_sockaddr2ipaddr(&src, sizeof_src, src_ipaddr, &port)) {
256                 free(buf);
257                 return -1;      /* Unknown address family, Die Die Die! */
258         }
259         *src_port = port;
260
261         fr_sockaddr2ipaddr(&dst, sizeof_dst, dst_ipaddr, &port);
262         *dst_port = port;
263
264         /*
265          *      Different address families should never happen.
266          */
267         if (src.ss_family != dst.ss_family) {
268                 free(buf);
269                 return -1;
270         }
271
272         /*
273          *      Tell the caller about the data
274          */
275         *pbuf = buf;
276
277         return data_len;
278 }
279
280 RADIUS_PACKET *vqp_recv(int sockfd)
281 {
282         uint8_t *ptr;
283         ssize_t length;
284         uint32_t id;
285         RADIUS_PACKET *packet;
286
287         /*
288          *      Allocate the new request data structure
289          */
290         if ((packet = malloc(sizeof(*packet))) == NULL) {
291                 fr_strerror_printf("out of memory");
292                 return NULL;
293         }
294         memset(packet, 0, sizeof(*packet));
295
296         packet->data_len = vqp_recvfrom(sockfd, &packet->data, 0,
297                                         &packet->src_ipaddr, &packet->src_port,
298                                         &packet->dst_ipaddr, &packet->dst_port);
299
300         /*
301          *      Check for socket errors.
302          */
303         if (packet->data_len < 0) {
304                 fr_strerror_printf("Error receiving packet: %s", strerror(errno));
305                 /* packet->data is NULL */
306                 free(packet);
307                 return NULL;
308         }
309
310
311         /*
312          *      We can only receive packets formatted in a way we
313          *      expect.  However, we accept MORE attributes in a
314          *      packet than normal implementations may send.
315          */
316         if (packet->data_len < VQP_HDR_LEN) {
317                 fr_strerror_printf("VQP packet is too short");
318                 rad_free(&packet);
319                 return NULL;
320         }
321
322         ptr = packet->data;
323
324         if (0) {
325                 int i;
326                 for (i = 0; i < packet->data_len; i++) {
327                         if ((i & 0x0f) == 0) fprintf(stderr, "%02x: ", i);
328                         fprintf(stderr, "%02x ", ptr[i]);
329                         if ((i & 0x0f) == 0x0f) fprintf(stderr, "\n");
330                 }
331           
332         }
333
334         if (ptr[3] > VQP_MAX_ATTRIBUTES) {
335                 fr_strerror_printf("Too many VQP attributes");
336                 rad_free(&packet);
337                 return NULL;
338         }
339
340         if (packet->data_len > VQP_HDR_LEN) {
341                 int attrlen;
342
343                 /*
344                  *      Skip the header.
345                  */
346                 ptr += VQP_HDR_LEN;
347                 length = packet->data_len - VQP_HDR_LEN;
348
349                 while (length > 0) {
350                         if (length < 7) {
351                                 fr_strerror_printf("Packet contains malformed attribute");
352                                 rad_free(&packet);
353                                 return NULL;
354                         }
355
356                         /*
357                          *      Attributes are 4 bytes
358                          *      0x00000c01 ... 0x00000c08
359                          */
360                         if ((ptr[0] != 0) || (ptr[1] != 0) ||
361                             (ptr[2] != 0x0c) || (ptr[3] < 1) || (ptr[3] > 8)) {
362                                 fr_strerror_printf("Packet contains invalid attribute");
363                                 rad_free(&packet);
364                                 return NULL;
365                         }
366
367                         /*
368                          *      Length is 2 bytes
369                          *
370                          *      We support lengths 1..253, for internal
371                          *      server reasons.  Also, there's no reason
372                          *      for bigger lengths to exist... admins
373                          *      won't be typing in a 32K vlan name.
374                          *
375                          *      Except for received ethernet frames...
376                          *      they get chopped to 253 internally.
377                          */
378                         if ((ptr[3] != 5) &&
379                             ((ptr[4] != 0) || (ptr[5] > MAX_VMPS_LEN))) {
380                                 fr_strerror_printf("Packet contains attribute with invalid length %02x %02x", ptr[4], ptr[5]);
381                                 rad_free(&packet);
382                                 return NULL;
383                         }
384                         attrlen = (ptr[4] << 8) | ptr[5];
385                         ptr += 6 + attrlen;
386                         length -= (6 + attrlen);
387                 }
388         }
389
390         packet->sockfd = sockfd;
391         packet->vps = NULL;
392
393         /*
394          *      This is more than a bit of a hack.
395          */
396         packet->code = PW_AUTHENTICATION_REQUEST;
397
398         memcpy(&id, packet->data + 4, 4);
399         packet->id = ntohl(id);
400
401         /*
402          *      FIXME: Create a fake "request authenticator", to
403          *      avoid duplicates?  Or is the VQP sequence number
404          *      adequate for this purpose?
405          */
406
407         return packet;
408 }
409
410 /*
411  *      We do NOT  mirror the old-style RADIUS code  that does encode,
412  *      sign && send in one function.  For VQP, the caller MUST perform
413  *      each task manually, and separately.
414  */
415 int vqp_send(RADIUS_PACKET *packet)
416 {
417         if (!packet || !packet->data || (packet->data_len < 8)) return -1;
418
419         /*
420          *      Don't print out the attributes, they were printed out
421          *      when it was encoded.
422          */
423
424         /*
425          *      And send it on it's way.
426          */
427         return vqp_sendto(packet->sockfd, packet->data, packet->data_len, 0,
428                           &packet->src_ipaddr, &packet->dst_ipaddr,
429                           packet->dst_port);
430 }
431
432
433 int vqp_decode(RADIUS_PACKET *packet)
434 {
435         uint8_t *ptr, *end;
436         int attribute, length;
437         VALUE_PAIR *vp, **tail;
438
439         if (!packet || !packet->data) return -1;
440
441         if (packet->data_len < VQP_HDR_LEN) return -1;
442
443         tail = &packet->vps;
444
445         vp = paircreate(PW_VQP_PACKET_TYPE, PW_TYPE_OCTETS);
446         if (!vp) {
447                 fr_strerror_printf("No memory");
448                 return -1;
449         }
450         vp->lvalue = packet->data[1];
451         debug_pair(vp);
452
453         *tail = vp;
454         tail = &(vp->next);
455
456         vp = paircreate(PW_VQP_ERROR_CODE, PW_TYPE_OCTETS);
457         if (!vp) {
458                 fr_strerror_printf("No memory");
459                 return -1;
460         }
461         vp->lvalue = packet->data[2];
462         debug_pair(vp);
463
464         *tail = vp;
465         tail = &(vp->next);
466
467         vp = paircreate(PW_VQP_SEQUENCE_NUMBER, PW_TYPE_OCTETS);
468         if (!vp) {
469                 fr_strerror_printf("No memory");
470                 return -1;
471         }
472         vp->lvalue = packet->id; /* already set by vqp_recv */
473         debug_pair(vp);
474
475         *tail = vp;
476         tail = &(vp->next);
477
478         ptr = packet->data + VQP_HDR_LEN;
479         end = packet->data + packet->data_len;
480
481         /*
482          *      Note that vqp_recv() MUST ensure that the packet is
483          *      formatted in a way we expect, and that vqp_recv() MUST
484          *      be called before vqp_decode().
485          */
486         while (ptr < end) {
487                 attribute = (ptr[2] << 8) | ptr[3];
488                 length = (ptr[4] << 8) | ptr[5];
489                 ptr += 6;
490
491                 /*
492                  *      Hack to get the dictionaries to work correctly.
493                  */
494                 attribute |= 0x2000;
495                 vp = paircreate(attribute, PW_TYPE_OCTETS);
496                 if (!vp) {
497                         pairfree(&packet->vps);
498
499                         fr_strerror_printf("No memory");
500                         return -1;
501                 }
502
503                 switch (vp->type) {
504                 case PW_TYPE_IPADDR:
505                         if (length == 4) {
506                                 memcpy(&vp->vp_ipaddr, ptr, 4);
507                                 vp->length = 4;
508                                 break;
509                         }
510                         vp->type = PW_TYPE_OCTETS;
511                         /* FALL-THROUGH */
512
513                 default:
514                 case PW_TYPE_OCTETS:
515                 case PW_TYPE_STRING:
516                         vp->length = (length > MAX_VMPS_LEN) ? MAX_VMPS_LEN : length;
517                         memcpy(vp->vp_octets, ptr, vp->length);
518                         vp->vp_octets[vp->length] = '\0';
519                         break;
520                 }
521                 ptr += length;
522                 debug_pair(vp);
523
524                 *tail = vp;
525                 tail = &(vp->next);
526         }
527
528         /*
529          *      FIXME: Map attributes to Calling-Station-Id, etc...
530          */
531
532         return 0;
533 }
534
535 /*
536  *      These are the MUST HAVE contents for a VQP packet.
537  *
538  *      We don't allow the caller to give less than these, because
539  *      it won't work.  We don't encode more than these, because the
540  *      clients will ignore it.
541  *
542  *      FIXME: Be more generous?  Look for CISCO + VQP attributes?
543  */
544 static int contents[5][VQP_MAX_ATTRIBUTES] = {
545         { 0,      0,      0,      0,      0,      0 },
546         { 0x0c01, 0x0c02, 0x0c03, 0x0c04, 0x0c07, 0x0c05 }, /* Join request */
547         { 0x0c03, 0x0c08, 0,      0,      0,      0 },  /* Join Response */
548         { 0x0c01, 0x0c02, 0x0c03, 0x0c04, 0x0c07, 0x0c08 }, /* Reconfirm */
549         { 0x0c03, 0x0c08, 0,      0,      0,      0 }
550 };
551
552 int vqp_encode(RADIUS_PACKET *packet, RADIUS_PACKET *original)
553 {
554         int i, code, length;
555         VALUE_PAIR *vp;
556         uint8_t *ptr;
557         VALUE_PAIR      *vps[VQP_MAX_ATTRIBUTES];
558
559         if (!packet) {
560                 fr_strerror_printf("Failed encoding VQP");
561                 return -1;
562         }
563
564         if (packet->data) return 0;
565
566         vp = pairfind(packet->vps, PW_VQP_PACKET_TYPE);
567         if (!vp) {
568                 fr_strerror_printf("Failed to find VQP-Packet-Type in response packet");
569                 return -1;
570         }
571
572         code = vp->lvalue;
573         if ((code < 1) || (code > 4)) {
574                 fr_strerror_printf("Invalid value %d for VQP-Packet-Type", code);
575                 return -1;
576         }
577
578         length = VQP_HDR_LEN;
579         memset(vps, 0, sizeof(vps));
580
581         vp = pairfind(packet->vps, PW_VQP_ERROR_CODE);
582
583         /*
584          *      FIXME: Map attributes from calling-station-Id, etc.
585          *
586          *      Maybe do this via rlm_vqp?  That's probably the
587          *      best place to add the code...
588          */
589
590         /*
591          *      No error: encode attributes.
592          */
593         if (!vp) for (i = 0; i < VQP_MAX_ATTRIBUTES; i++) {
594                 if (!contents[code][i]) break;
595
596                 vps[i] = pairfind(packet->vps, contents[code][i] | 0x2000);
597
598                 /*
599                  *      FIXME: Print the name...
600                  */
601                 if (!vps[i]) {
602                         fr_strerror_printf("Failed to find VQP attribute %02x",
603                                    contents[code][i]);
604                         return -1;
605                 }
606
607                 length += 6;
608                 length += vps[i]->length;
609         }
610
611         packet->data = malloc(length);
612         if (!packet->data) {
613                 fr_strerror_printf("No memory");
614                 return -1;
615         }
616         packet->data_len = length;
617
618         ptr = packet->data;
619
620         ptr[0] = VQP_VERSION;
621         ptr[1] = code;
622
623         if (!vp) {
624                 ptr[2] = 0;
625         } else {
626                 ptr[2] = vp->lvalue & 0xff;
627                 return 0;
628         }
629
630         /*
631          *      The number of attributes is hard-coded.
632          */
633         if ((code == 1) || (code == 3)) {
634                 uint32_t sequence;
635
636                 ptr[3] = VQP_MAX_ATTRIBUTES;
637
638                 sequence = htonl(packet->id);
639                 memcpy(ptr + 4, &sequence, 4);
640         } else {
641                 if (!original) {
642                         fr_strerror_printf("Cannot send VQP response without request");
643                         return -1;
644                 }
645
646                 /*
647                  *      Packet Sequence Number
648                  */
649                 memcpy(ptr + 4, original->data + 4, 4);
650
651                 ptr[3] = 2;
652         }
653
654         ptr += 8;
655
656         /*
657          *      Encode the VP's.
658          */
659         for (i = 0; i < VQP_MAX_ATTRIBUTES; i++) {
660                 if (!vps[i]) break;
661                 vp = vps[i];
662
663                 debug_pair(vp);
664
665                 /*
666                  *      Type.  Note that we look at only the lower 8
667                  *      bits, as the upper 8 bits have been hacked.
668                  *      See also dictionary.vqp
669                  */
670                 ptr[0] = 0;
671                 ptr[1] = 0;
672                 ptr[2] = 0x0c;
673                 ptr[3] = vp->attribute & 0xff;
674
675                 /* Length */
676                 ptr[4] = 0;
677                 ptr[5] = vp->length & 0xff;
678
679                 ptr += 6;
680
681                 /* Data */
682                 switch (vp->type) {
683                 case PW_TYPE_IPADDR:
684                         memcpy(ptr, &vp->vp_ipaddr, 4);
685                         break;
686
687                 default:
688                 case PW_TYPE_OCTETS:
689                 case PW_TYPE_STRING:
690                         memcpy(ptr, vp->vp_octets, vp->length);
691                         break;
692                 }
693                 ptr += vp->length;
694         }
695
696         return 0;
697 }
698 #endif