1 /*
2  * Example IMV for TNC testing
3  * Copyright (c) 2014, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/tnc.h"
13 
14 static int initialized = 0;
15 static TNC_IMVID my_id = -1;
16 static TNC_TNCS_ReportMessageTypesPointer report_message_types = NULL;
17 static TNC_TNCS_SendMessagePointer send_message = NULL;
18 static TNC_TNCS_RequestHandshakeRetryPointer request_retry = NULL;
19 TNC_TNCS_ProvideRecommendationPointer provide_recomm = NULL;
20 
21 static TNC_MessageType message_types[] =
22 {
23 	(TNC_VENDORID_ANY << 8) | TNC_SUBTYPE_ANY
24 };
25 
26 
TNC_IMV_Initialize(TNC_IMVID imvID,TNC_Version minVersion,TNC_Version maxVersion,TNC_Version * pOutActualVersion)27 TNC_Result TNC_IMV_Initialize(
28 	/*in*/ TNC_IMVID imvID,
29 	/*in*/ TNC_Version minVersion,
30 	/*in*/ TNC_Version maxVersion,
31 	/*out*/ TNC_Version *pOutActualVersion)
32 {
33 	wpa_printf(MSG_INFO,
34 		   "IMV(hostap2) %s(imvID=%u, minVersion=%u, maxVersion=%u)",
35 		   __func__, (unsigned) imvID, (unsigned) minVersion,
36 		   (unsigned) maxVersion);
37 
38 	if (initialized)
39 		return TNC_RESULT_ALREADY_INITIALIZED;
40 
41 	if (minVersion < TNC_IFIMV_VERSION_1 ||
42 	    maxVersion > TNC_IFIMV_VERSION_1)
43 		return TNC_RESULT_NO_COMMON_VERSION;
44 
45 	if (!pOutActualVersion)
46 		return TNC_RESULT_INVALID_PARAMETER;
47 	*pOutActualVersion = TNC_IFIMV_VERSION_1;
48 
49 	initialized = 1;
50 	my_id = imvID;
51 
52 	return TNC_RESULT_SUCCESS;
53 }
54 
55 
TNC_IMV_NotifyConnectionChange(TNC_IMVID imvID,TNC_ConnectionID connectionID,TNC_ConnectionState newState)56 TNC_Result TNC_IMV_NotifyConnectionChange(
57 	/*in*/ TNC_IMVID imvID,
58 	/*in*/ TNC_ConnectionID connectionID,
59 	/*in*/ TNC_ConnectionState newState)
60 {
61 	wpa_printf(MSG_INFO,
62 		   "IMV(hostap2) %s(imvID=%u, connectionID=%u, newState=%u)",
63 		   __func__, (unsigned) imvID, (unsigned) connectionID,
64 		   (unsigned) newState);
65 
66 	if (!initialized)
67 		return TNC_RESULT_NOT_INITIALIZED;
68 
69 	if (imvID != my_id)
70 		return TNC_RESULT_INVALID_PARAMETER;
71 
72 	/* TODO: call TNC_TNCS_ProvideRecommendation */
73 
74 	return TNC_RESULT_SUCCESS;
75 }
76 
77 
TNC_IMV_ReceiveMessage(TNC_IMVID imvID,TNC_ConnectionID connectionID,TNC_BufferReference message,TNC_UInt32 messageLength,TNC_MessageType messageType)78 TNC_Result TNC_IMV_ReceiveMessage(
79 	/*in*/ TNC_IMVID imvID,
80 	/*in*/ TNC_ConnectionID connectionID,
81 	/*in*/ TNC_BufferReference message,
82 	/*in*/ TNC_UInt32 messageLength,
83 	/*in*/ TNC_MessageType messageType)
84 {
85 	TNC_Result res;
86 
87 	wpa_printf(MSG_INFO,
88 		   "IMV(hostap2) %s(imvID=%u, connectionID=%u, messageType=%u)",
89 		   __func__, (unsigned) imvID, (unsigned) connectionID,
90 		   (unsigned) messageType);
91 	wpa_hexdump_ascii(MSG_INFO, "IMV(hostap2) message",
92 			  message, messageLength);
93 
94 	if (!send_message)
95 		return TNC_RESULT_FATAL;
96 
97 	if (messageType == 1 && messageLength == 5 &&
98 	    os_memcmp(message, "hello", 5) == 0) {
99 		char *msg = "hello";
100 
101 		res = send_message(imvID, connectionID, msg, os_strlen(msg), 1);
102 		if (res != TNC_RESULT_SUCCESS)
103 			return res;
104 	}
105 
106 	if (messageType == 1 && messageLength == 8 &&
107 	    os_memcmp(message, "i'm fine", 8) == 0) {
108 		if (!provide_recomm)
109 			return TNC_RESULT_FATAL;
110 		res = provide_recomm(imvID, connectionID,
111 				     TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
112 				     TNC_IMV_EVALUATION_RESULT_COMPLIANT);
113 		if (res != TNC_RESULT_SUCCESS)
114 			return res;
115 	}
116 
117 	return TNC_RESULT_SUCCESS;
118 }
119 
120 
TNC_IMV_SolicitRecommendation(TNC_IMVID imvID,TNC_ConnectionID connectionID)121 TNC_Result TNC_IMV_SolicitRecommendation(
122 	/*in*/ TNC_IMVID imvID,
123 	/*in*/ TNC_ConnectionID connectionID)
124 {
125 	wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u, connectionID=%u)",
126 		   __func__, (unsigned) imvID, (unsigned) connectionID);
127 
128 	if (!initialized)
129 		return TNC_RESULT_NOT_INITIALIZED;
130 
131 	if (imvID != my_id)
132 		return TNC_RESULT_INVALID_PARAMETER;
133 
134 	/* TODO: call TNC_TNCS_ProvideRecommendation */
135 
136 	return TNC_RESULT_SUCCESS;
137 }
138 
139 
TNC_IMV_BatchEnding(TNC_IMVID imvID,TNC_ConnectionID connectionID)140 TNC_Result TNC_IMV_BatchEnding(
141 	/*in*/ TNC_IMVID imvID,
142 	/*in*/ TNC_ConnectionID connectionID)
143 {
144 	wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u, connectionID=%u)",
145 		   __func__, (unsigned) imvID, (unsigned) connectionID);
146 
147 	return TNC_RESULT_SUCCESS;
148 }
149 
150 
TNC_IMV_Terminate(TNC_IMVID imvID)151 TNC_Result TNC_IMV_Terminate(
152 	/*in*/ TNC_IMVID imvID)
153 {
154 	wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u)",
155 		   __func__, (unsigned) imvID);
156 
157 	return TNC_RESULT_SUCCESS;
158 }
159 
160 
TNC_IMV_ProvideBindFunction(TNC_IMVID imvID,TNC_TNCS_BindFunctionPointer bindFunction)161 TNC_Result TNC_IMV_ProvideBindFunction(
162 	/*in*/ TNC_IMVID imvID,
163 	/*in*/ TNC_TNCS_BindFunctionPointer bindFunction)
164 {
165 	TNC_Result res;
166 
167 	wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u)",
168 		   __func__, (unsigned) imvID);
169 
170 	if (!initialized)
171 		return TNC_RESULT_NOT_INITIALIZED;
172 
173 	if (imvID != my_id || !bindFunction)
174 		return TNC_RESULT_INVALID_PARAMETER;
175 
176 	if (bindFunction(imvID, "TNC_TNCS_ReportMessageTypes",
177 			 (void **) &report_message_types) !=
178 	    TNC_RESULT_SUCCESS ||
179 	    !report_message_types)
180 		return TNC_RESULT_FATAL;
181 
182 	if (bindFunction(imvID, "TNC_TNCS_SendMessage",
183 			 (void **) &send_message) != TNC_RESULT_SUCCESS ||
184 	    !send_message)
185 		return TNC_RESULT_FATAL;
186 
187 	if (bindFunction(imvID, "TNC_TNCS_RequestHandshakeRetry",
188 			 (void **) &request_retry) != TNC_RESULT_SUCCESS ||
189 	    !request_retry)
190 		return TNC_RESULT_FATAL;
191 
192 	if (bindFunction(imvID, "TNC_TNCS_ProvideRecommendation",
193 			 (void **) &provide_recomm) != TNC_RESULT_SUCCESS ||
194 	    !provide_recomm)
195 		return TNC_RESULT_FATAL;
196 
197 	res = report_message_types(imvID, message_types,
198 				   ARRAY_SIZE(message_types));
199 	if (res != TNC_RESULT_SUCCESS)
200 		return res;
201 
202 	return TNC_RESULT_SUCCESS;
203 }
204