1  /*
2   * EAP server method registration
3   * Copyright (c) 2004-2009, 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 "eap_i.h"
13  #include "eap_methods.h"
14  
15  
16  static struct eap_method *eap_methods;
17  
18  
19  /**
20   * eap_server_get_eap_method - Get EAP method based on type number
21   * @vendor: EAP Vendor-Id (0 = IETF)
22   * @method: EAP type number
23   * Returns: Pointer to EAP method or %NULL if not found
24   */
eap_server_get_eap_method(int vendor,enum eap_type method)25  const struct eap_method * eap_server_get_eap_method(int vendor,
26  						    enum eap_type method)
27  {
28  	struct eap_method *m;
29  	for (m = eap_methods; m; m = m->next) {
30  		if (m->vendor == vendor && m->method == method)
31  			return m;
32  	}
33  	return NULL;
34  }
35  
36  
37  /**
38   * eap_server_get_type - Get EAP type for the given EAP method name
39   * @name: EAP method name, e.g., TLS
40   * @vendor: Buffer for returning EAP Vendor-Id
41   * Returns: EAP method type or %EAP_TYPE_NONE if not found
42   *
43   * This function maps EAP type names into EAP type numbers based on the list of
44   * EAP methods included in the build.
45   */
eap_server_get_type(const char * name,int * vendor)46  enum eap_type eap_server_get_type(const char *name, int *vendor)
47  {
48  	struct eap_method *m;
49  	for (m = eap_methods; m; m = m->next) {
50  		if (os_strcmp(m->name, name) == 0) {
51  			*vendor = m->vendor;
52  			return m->method;
53  		}
54  	}
55  	*vendor = EAP_VENDOR_IETF;
56  	return EAP_TYPE_NONE;
57  }
58  
59  
60  /**
61   * eap_server_method_alloc - Allocate EAP server method structure
62   * @version: Version of the EAP server method interface (set to
63   * EAP_SERVER_METHOD_INTERFACE_VERSION)
64   * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
65   * @method: EAP type number (EAP_TYPE_*)
66   * @name: Name of the method (e.g., "TLS")
67   * Returns: Allocated EAP method structure or %NULL on failure
68   *
69   * The returned structure should be freed with eap_server_method_free() when it
70   * is not needed anymore.
71   */
eap_server_method_alloc(int version,int vendor,enum eap_type method,const char * name)72  struct eap_method * eap_server_method_alloc(int version, int vendor,
73  					    enum eap_type method,
74  					    const char *name)
75  {
76  	struct eap_method *eap;
77  	eap = os_zalloc(sizeof(*eap));
78  	if (eap == NULL)
79  		return NULL;
80  	eap->version = version;
81  	eap->vendor = vendor;
82  	eap->method = method;
83  	eap->name = name;
84  	return eap;
85  }
86  
87  
88  /**
89   * eap_server_method_free - Free EAP server method structure
90   * @method: Method structure allocated with eap_server_method_alloc()
91   */
eap_server_method_free(struct eap_method * method)92  static void eap_server_method_free(struct eap_method *method)
93  {
94  	os_free(method);
95  }
96  
97  
98  /**
99   * eap_server_method_register - Register an EAP server method
100   * @method: EAP method to register from eap_server_method_alloc()
101   * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
102   * has already been registered
103   *
104   * Each EAP server method needs to call this function to register itself as a
105   * supported EAP method. The caller must not free the allocated method data
106   * regardless of the return value.
107   */
eap_server_method_register(struct eap_method * method)108  int eap_server_method_register(struct eap_method *method)
109  {
110  	struct eap_method *m, *last = NULL;
111  
112  	if (method == NULL || method->name == NULL ||
113  	    method->version != EAP_SERVER_METHOD_INTERFACE_VERSION) {
114  		eap_server_method_free(method);
115  		return -1;
116  	}
117  
118  	for (m = eap_methods; m; m = m->next) {
119  		if ((m->vendor == method->vendor &&
120  		     m->method == method->method) ||
121  		    os_strcmp(m->name, method->name) == 0) {
122  			eap_server_method_free(method);
123  			return -2;
124  		}
125  		last = m;
126  	}
127  
128  	if (last)
129  		last->next = method;
130  	else
131  		eap_methods = method;
132  
133  	return 0;
134  }
135  
136  
137  /**
138   * eap_server_unregister_methods - Unregister EAP server methods
139   *
140   * This function is called at program termination to unregister all EAP server
141   * methods.
142   */
eap_server_unregister_methods(void)143  void eap_server_unregister_methods(void)
144  {
145  	struct eap_method *m;
146  
147  	while (eap_methods) {
148  		m = eap_methods;
149  		eap_methods = eap_methods->next;
150  
151  		if (m->free)
152  			m->free(m);
153  		else
154  			eap_server_method_free(m);
155  	}
156  }
157  
158  
159  /**
160   * eap_server_get_name - Get EAP method name for the given EAP type
161   * @vendor: EAP Vendor-Id (0 = IETF)
162   * @type: EAP method type
163   * Returns: EAP method name, e.g., TLS, or "unknown" if not found
164   *
165   * This function maps EAP type numbers into EAP type names based on the list of
166   * EAP methods included in the build.
167   */
eap_server_get_name(int vendor,enum eap_type type)168  const char * eap_server_get_name(int vendor, enum eap_type type)
169  {
170  	struct eap_method *m;
171  	if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
172  		return "expanded";
173  	for (m = eap_methods; m; m = m->next) {
174  		if (m->vendor == vendor && m->method == type)
175  			return m->name;
176  	}
177  	return "unknown";
178  }
179