1/* 2 * $Id: radius.c,v 1.1.1.1 2008/10/15 03:30:50 james26_jang Exp $ 3 * 4 * Copyright (C) 1996 Lars Fenneberg 5 * 6 * See the file COPYRIGHT for the respective terms and conditions. 7 * If the file is missing contact me at lf@elemental.net 8 * and I'll send you a copy. 9 * 10 */ 11 12#include <config.h> 13#include <includes.h> 14#include <radiusclient.h> 15#include <messages.h> 16#include <radlogin.h> 17 18extern ENV *env; 19 20LFUNC auth_radius(UINT4 client_port, char *username, char *passwd) 21{ 22 23 VALUE_PAIR *send, *received, *vp, *service_vp; 24 UINT4 service, ftype, ctype; 25 char msg[4096], *p, username_realm[256]; 26 char name[2048], value[2048]; /* more than enough */ 27 int result; 28 char *default_realm, *service_str, *ftype_str; 29 DICT_VALUE *dval; 30 31 send = received = NULL; 32 33 /* 34 * Determine and fill in Service-Type 35 */ 36 37#ifdef SCP 38 /* determine based on the username what kind of service is requested. 39 this allows you to use one password for all accounts, but the 40 Merit radiusd supplies you just with the right information you 41 need for the specified service type -lf, 03/15/96 */ 42 43 switch (*username) 44 { 45 case 'S': 46 service = PW_FRAMED; 47 ftype = PW_SLIP; 48 ctype = 0; 49 username++; 50 break; 51 case 'C': 52 service = PW_FRAMED; 53 ftype = PW_SLIP; 54 ctype = PW_VAN_JACOBSON_TCP_IP; 55 username++; 56 break; 57 case 'P': 58 service = PW_FRAMED; 59 ftype = PW_PPP; 60 ctype = 0; 61 username++; 62 break; 63 default: 64 service = PW_LOGIN; 65 ftype = 0; 66 ctype = 0; 67 break; 68 } 69#else 70 service = PW_LOGIN; 71 ftype = 0; 72 ctype = 0; 73#endif 74 75 if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0, VENDOR_NONE) == NULL) 76 return (LFUNC) NULL; 77 78 /* Fill in Framed-Protocol, if neccessary */ 79 80 if (ftype != 0) 81 { 82 if (rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &ftype, 0, VENDOR_NONE) == NULL) 83 return (LFUNC) NULL; 84 } 85 86 /* Fill in Framed-Compression, if neccessary */ 87 88 if (ctype != 0) 89 { 90 if (rc_avpair_add(&send, PW_FRAMED_COMPRESSION, &ctype, 0, VENDOR_NONE) == NULL) 91 return (LFUNC) NULL; 92 } 93 94 /* 95 * Fill in User-Name 96 */ 97 98 strncpy(username_realm, username, sizeof(username_realm)); 99 100 /* Append default realm */ 101 default_realm = rc_conf_str("default_realm"); 102 103 if ((strchr(username_realm, '@') == NULL) && default_realm && 104 ((*default_realm) != '\0')) 105 { 106 strncat(username_realm, "@", sizeof(username_realm)); 107 strncat(username_realm, default_realm, sizeof(username_realm)); 108 } 109 110 if (rc_avpair_add(&send, PW_USER_NAME, username_realm, 0, VENDOR_NONE) == NULL) 111 return (LFUNC) NULL; 112 113 /* 114 * Fill in User-Password 115 */ 116 117 if (rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE) == NULL) 118 return (LFUNC) NULL; 119 120 result = rc_auth(client_port, send, &received, msg, NULL); 121 122 if (result == OK_RC) 123 { 124 /* Set up a running count of attributes saved. */ 125 int acount[256], attr; 126 127 memset(acount, 0, sizeof(acount)); 128 129 rc_add_env(env, "RADIUS_USER_NAME", username); 130 131 vp = received; 132 133 /* map-- keep track of the attributes so that we know 134 when to add the delimiters. Note that we can only 135 handle attributes < 256, which is the standard anyway. */ 136 137 while (vp) 138 { 139 strcpy(name, "RADIUS_"); 140 if (rc_avpair_tostr(vp, name+7, sizeof(name)-7, value, sizeof(value)) < 0) { 141 rc_avpair_free(send); 142 rc_avpair_free(received); 143 return (LFUNC) NULL; 144 } 145 146 /* Translate "-" => "_" and uppercase*/ 147 for(p = name; *p; p++) { 148 *p = toupper(*p); 149 if (*p == '-') *p = '_'; 150 } 151 152 /* Add to the attribute count and append the var 153 if necessary. */ 154 if ((attr = vp->attribute) < 256) 155 { 156 int count; 157 if ((count = acount[attr]++) > 0) { 158 char buf[10]; 159 sprintf(buf, "_%d", count); 160 strcat(name,buf); 161 } 162 } 163 164 if (rc_add_env(env, name, value) < 0) 165 { 166 rc_avpair_free(send); 167 rc_avpair_free(received); 168 return (LFUNC) NULL; 169 } 170 171 vp = vp->next; 172 } 173 174 service_str = "(unknown)"; 175 ftype_str = NULL; 176 177 if ((service_vp = rc_avpair_get(received, PW_SERVICE_TYPE)) != NULL) 178 if ((dval = rc_dict_getval(service_vp->lvalue, service_vp->name)) != NULL) { 179 service_str = dval->name; 180 } 181 182 if (service_vp && (service_vp->lvalue == PW_FRAMED) && 183 ((vp = rc_avpair_get(received, PW_FRAMED_PROTOCOL)) != NULL)) 184 if ((dval = rc_dict_getval(vp->lvalue, vp->name)) != NULL) { 185 ftype_str = dval->name; 186 } 187 188 rc_log(LOG_NOTICE, "authentication OK, username %s, service %s%s%s", 189 username, service_str,(ftype_str)?"/":"", (ftype_str)?ftype_str:""); 190 191 if (msg && (*msg != '\0')) 192 printf(SC_SERVER_REPLY, msg); 193 else 194 printf(SC_RADIUS_OK); 195 196 rc_avpair_free(send); 197 rc_avpair_free(received); 198 199 return radius_login; 200 } 201 else 202 { 203 rc_log(LOG_NOTICE, "authentication FAILED, type RADIUS, username %s", 204 username_realm); 205 if (msg && (*msg != '\0')) 206 printf(SC_SERVER_REPLY, msg); 207 else 208 printf(SC_RADIUS_FAILED); 209 } 210 211 rc_avpair_free(send); 212 if (received) 213 rc_avpair_free(received); 214 215 return (LFUNC) NULL; 216} 217 218void 219radius_login(char *username) 220{ 221 char *login_radius = rc_conf_str("login_radius"); 222 223 execle(login_radius, login_radius, NULL, env->env); 224 225 rc_log(LOG_ERR, "couldn't execute %s: %s", login_radius, strerror(errno)); 226 fprintf(stderr, "couldn't execute %s: %s", login_radius, strerror(errno)); 227 228 sleep(1); /* give the user time to read */ 229 exit(ERROR_RC); 230} 231