1c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/*
20a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * EAP server method registration
30a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
40a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
50a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * This software may be distributed under the terms of the BSD license.
60a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * See README for more details.
70a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
80a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
90a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "includes.h"
100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "common.h"
120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "eap_i.h"
130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "eap_methods.h"
140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic struct eap_method *eap_methods;
170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_get_eap_method - Get EAP method based on type number
210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @vendor: EAP Vendor-Id (0 = IETF)
220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @method: EAP type number
230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Returns: Pointer to EAP method or %NULL if not found
240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangconst struct eap_method * eap_server_get_eap_method(int vendor, EapType method)
260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *m;
280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (m = eap_methods; m; m = m->next) {
290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (m->vendor == vendor && m->method == method)
300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return m;
310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return NULL;
330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_get_type - Get EAP type for the given EAP method name
380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @name: EAP method name, e.g., TLS
390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @vendor: Buffer for returning EAP Vendor-Id
400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Returns: EAP method type or %EAP_TYPE_NONE if not found
410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * This function maps EAP type names into EAP type numbers based on the list of
430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * EAP methods included in the build.
440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih WangEapType eap_server_get_type(const char *name, int *vendor)
460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *m;
480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (m = eap_methods; m; m = m->next) {
490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (os_strcmp(m->name, name) == 0) {
500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			*vendor = m->vendor;
510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return m->method;
520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	*vendor = EAP_VENDOR_IETF;
550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return EAP_TYPE_NONE;
560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_method_alloc - Allocate EAP server method structure
610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @version: Version of the EAP server method interface (set to
620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * EAP_SERVER_METHOD_INTERFACE_VERSION)
630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @method: EAP type number (EAP_TYPE_*)
650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @name: Name of the method (e.g., "TLS")
660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Returns: Allocated EAP method structure or %NULL on failure
670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * The returned structure should be freed with eap_server_method_free() when it
690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * is not needed anymore.
700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstruct eap_method * eap_server_method_alloc(int version, int vendor,
720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					    EapType method, const char *name)
730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *eap;
750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eap = os_zalloc(sizeof(*eap));
760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (eap == NULL)
770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return NULL;
780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eap->version = version;
790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eap->vendor = vendor;
800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eap->method = method;
810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eap->name = name;
820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return eap;
830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_method_free - Free EAP server method structure
880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @method: Method structure allocated with eap_server_method_alloc()
890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangvoid eap_server_method_free(struct eap_method *method)
910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	os_free(method);
930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_method_register - Register an EAP server method
980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @method: EAP method to register
990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
1000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * has already been registered
1010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
1020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Each EAP server method needs to call this function to register itself as a
1030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * supported EAP method.
1040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
1050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint eap_server_method_register(struct eap_method *method)
1060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *m, *last = NULL;
1080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (method == NULL || method->name == NULL ||
110c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	    method->version != EAP_SERVER_METHOD_INTERFACE_VERSION)
1110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return -1;
1120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (m = eap_methods; m; m = m->next) {
114c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		if ((m->vendor == method->vendor &&
1150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		     m->method == method->method) ||
1160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		    os_strcmp(m->name, method->name) == 0)
1170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return -2;
1180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		last = m;
1190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (last)
1220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		last->next = method;
1230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	else
1240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		eap_methods = method;
1250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return 0;
1270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
1310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_unregister_methods - Unregister EAP server methods
1320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
1330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * This function is called at program termination to unregister all EAP server
1340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * methods.
1350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
1360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangvoid eap_server_unregister_methods(void)
1370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *m;
1390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	while (eap_methods) {
1410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		m = eap_methods;
1420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		eap_methods = eap_methods->next;
1430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (m->free)
1450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			m->free(m);
1460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		else
1470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			eap_server_method_free(m);
1480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/**
1530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * eap_server_get_name - Get EAP method name for the given EAP type
1540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @vendor: EAP Vendor-Id (0 = IETF)
1550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * @type: EAP method type
1560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Returns: EAP method name, e.g., TLS, or %NULL if not found
1570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
1580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * This function maps EAP type numbers into EAP type names based on the list of
1590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * EAP methods included in the build.
1600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
1610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangconst char * eap_server_get_name(int vendor, EapType type)
1620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct eap_method *m;
1640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
1650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return "expanded";
1660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (m = eap_methods; m; m = m->next) {
1670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (m->vendor == vendor && m->method == type)
1680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return m->name;
1690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return NULL;
171c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh}
1720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang