GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libradius/radius_msgauth.c Lines: 40 43 93.0 %
Date: 2017-11-07 Branches: 9 12 75.0 %

Line Branch Exec Source
1
/*	$OpenBSD: radius_msgauth.c,v 1.1 2015/07/20 23:52:29 yasuoka Exp $ */
2
3
/*-
4
 * Copyright (c) 2009 Internet Initiative Japan Inc.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE"AUTHOR" AND CONTRIBUTORS AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <netinet/in.h>
32
33
#include <stdbool.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
38
#include <openssl/hmac.h>
39
40
#include "radius.h"
41
42
#include "radius_local.h"
43
44
static void
45
radius_calc_message_authenticator(RADIUS_PACKET * packet, const char *secret,
46
    void *ma)
47
{
48
	const RADIUS_ATTRIBUTE	*attr;
49
	const RADIUS_ATTRIBUTE	*end;
50
56
	u_char			 zero16[16];
51
28
	HMAC_CTX		 ctx;
52
28
	int			 mdlen;
53
54
28
	memset(zero16, 0, sizeof(zero16));
55
56
28
	HMAC_Init(&ctx, secret, strlen(secret), EVP_md5());
57
58
	/*
59
	 * Traverse the radius packet.
60
	 */
61
28
	if (packet->request != NULL) {
62
12
		HMAC_Update(&ctx, (const u_char *)packet->pdata, 4);
63
24
		HMAC_Update(&ctx, (unsigned char *)packet->request->pdata
64
12
		    ->authenticator, 16);
65
12
	} else {
66
16
		HMAC_Update(&ctx, (const u_char *)packet->pdata,
67
		    sizeof(RADIUS_PACKET_DATA));
68
	}
69
70
28
	attr = ATTRS_BEGIN(packet->pdata);
71
28
	end = ATTRS_END(packet->pdata);
72
73
168
	for (; attr < end; ATTRS_ADVANCE(attr)) {
74
56
		if (attr->type == RADIUS_TYPE_MESSAGE_AUTHENTICATOR) {
75
28
			HMAC_Update(&ctx, (u_char *)attr, 2);
76
28
			HMAC_Update(&ctx, (u_char *)zero16, sizeof(zero16));
77
28
		} else
78
28
			HMAC_Update(&ctx, (u_char *)attr, (int) attr->length);
79
	}
80
81
28
	HMAC_Final(&ctx, (u_char *)ma, &mdlen);
82
83
28
	HMAC_cleanup(&ctx);
84
28
}
85
86
int
87
radius_put_message_authenticator(RADIUS_PACKET * packet, const char *secret)
88
{
89
16
	u_char	 ma[16];
90
91
	/*
92
	 * It is not required to initialize ma
93
	 * because content of Message-Authenticator attribute is assumed zero
94
	 * during calculation.
95
	 */
96
16
	if (radius_put_raw_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR,
97
16
		ma, sizeof(ma)) != 0)
98
		return (-1);
99
100
8
	return (radius_set_message_authenticator(packet, secret));
101
8
}
102
103
int
104
radius_set_message_authenticator(RADIUS_PACKET * packet, const char *secret)
105
{
106
24
	u_char	 ma[16];
107
108
12
	radius_calc_message_authenticator(packet, secret, ma);
109
110
24
	return (radius_set_raw_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR,
111
	    ma, sizeof(ma)));
112
12
}
113
114
int
115
radius_check_message_authenticator(RADIUS_PACKET * packet, const char *secret)
116
{
117
	int	 rval;
118
32
	size_t	 len;
119
16
	u_char	 ma0[16], ma1[16];
120
121
16
	radius_calc_message_authenticator(packet, secret, ma0);
122
123
16
	len = sizeof(ma1);
124
32
	if ((rval = radius_get_raw_attr(packet,
125
32
		    RADIUS_TYPE_MESSAGE_AUTHENTICATOR, ma1, &len)) != 0)
126
		return (rval);
127
128
16
	if (len != sizeof(ma1))
129
		return (-1);
130
131
16
	return (memcmp(ma0, ma1, sizeof(ma1)));
132
16
}