/[radius]/radius/radiusd/proxy.c
ViewVC logotype

Diff of /radius/radiusd/proxy.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.43 by gray, Fri Apr 18 05:27:10 2003 UTC revision 1.44 by gray, Fri Apr 25 22:48:55 2003 UTC
# Line 45  static char rcsid[] = Line 45  static char rcsid[] =
45    
46  static PROXY_ID *proxy_id;  static PROXY_ID *proxy_id;
47    
48  void proxy_addrequest(RADIUS_REQ *radreq);  /* ************************************************************************* */
49  static void passwd_recode(VALUE_PAIR *pair,  /* Functions local to this module */
50                            char *new_secret, char *new_vector, RADIUS_REQ *req);  
51  static int proxy_send_request(int fd, RADIUS_REQ *radreq);  static UINT4
52  static UINT4 get_socket_addr(int fd);  get_socket_addr(int fd)
53    {
54            struct sockaddr_in sin;
55            int len = sizeof(sin);
56            UINT4 ip = 0;
57    
58            if (getsockname(fd, (struct sockaddr*)&sin, &len) == 0)
59                    ip = sin.sin_addr.s_addr;
60    
61            if (ip == INADDR_ANY)
62                    ip = ref_ip;
63            return ip;
64    }
65    
66    
67    /*
68     *      Decode a password and encode it again.
69     */
70    static void
71    passwd_recode(VALUE_PAIR *pass_pair, char *new_secret, char *new_vector,
72                  RADIUS_REQ *req)
73    {
74            char    password[AUTH_STRING_LEN+1];
75            req_decrypt_password(password, req, pass_pair);
76            string_free(pass_pair->avp_strvalue);
77            encrypt_password(pass_pair, password, new_vector, new_secret);
78            /* Don't let the cleantext hang around */
79            memset(password, 0, AUTH_STRING_LEN);
80    }
81    
82    /* ************************************************************************* */
83    /* Functions for finding the matching request in the list of outstanding ones.
84     * There appear to be two cases: i) when the remote server retains the
85     * Proxy-State A/V pair, which seems to correspond to RFC 2865,
86     * and ii) when the remote server drops the Proxy-State pair.
87     */
88    
89    int
90    proxy_cmp(RADIUS_REQ *qr, RADIUS_REQ *r)
91    {
92            VALUE_PAIR *p, *proxy_state_pair = NULL;
93            PROXY_STATE *state;
94            
95            if (!qr->server) {
96                    debug(100,("no proxy server"));
97                    return 1;
98            }
99            /* Find the last PROXY_STATE attribute. */
100            for (p = r->request; p; p = p->next) {
101                    if (p->attribute == DA_PROXY_STATE)
102                            proxy_state_pair = p;
103            }
104            
105            state = proxy_state_pair ?
106                       (PROXY_STATE *)proxy_state_pair->avp_strvalue : NULL;
107            
108            if (state) {
109                    debug(1,
110                          ("state: ipaddr %08x, id %u, proxy_id %u, rem_ipaddr %08x",
111                           state->ipaddr,
112                           state->id,
113                           state->proxy_id,
114                           state->rem_ipaddr));
115                    
116                    if (state->proxy_id   == r->id
117                        && state->rem_ipaddr == r->ipaddr) {
118                            debug(10, ("(old=data) id %d %d, ipaddr %#8x %#8x, proxy_id %d %d, server_addr %#8x %#8x",
119                                       qr->id, state->id,
120                                       qr->ipaddr, state->ipaddr,
121                                       qr->server_id, state->proxy_id,
122                                       qr->server->addr, state->rem_ipaddr));
123            
124                            if (state->ipaddr == qr->ipaddr
125                                && state->id  == qr->id
126                                && state->proxy_id == qr->server_id
127                                && state->rem_ipaddr == qr->server->addr) {
128                                    debug(1,("EQUAL!!!"));
129                                    return 0;
130                            }
131                    }
132            } else if (qr->server_id) {
133                    debug(10, ("(old=data) id %d %d, ipaddr %#8x %#8x",
134                               qr->server_id,
135                               r->id,
136                               qr->server->addr,
137                               r->ipaddr));
138                            
139                    if (r->ipaddr == qr->server->addr
140                        && r->id == qr->server_id)
141                            return 0;
142            }
143            return 1;
144    }
145    
146  /* ************************************************************************* */  /* ************************************************************************* */
147  /* Proxy-Id functions */  /* Proxy-Id functions */
# Line 70  static UINT4 get_socket_addr(int fd); Line 162  static UINT4 get_socket_addr(int fd);
162   * If we don't have one, create it and initialize to zero.   * If we don't have one, create it and initialize to zero.
163   */   */
164  u_char  u_char
165  next_proxy_id(ipaddr)  next_proxy_id(UINT4 ipaddr)
         UINT4 ipaddr;  
166  {  {
167          PROXY_ID *p;          PROXY_ID *p;
168            
169          for (p = proxy_id; p; p = p->next)          for (p = proxy_id; p; p = p->next)
170                  if (p->ipaddr == ipaddr)                  if (p->ipaddr == ipaddr)
171                          break;                          break;
# Line 110  proxy_cleanup() Line 201  proxy_cleanup()
201  }  }
202    
203  /* ************************************************************************* */  /* ************************************************************************* */
 /* Request-queue functions */  
   
 /* rad_proxy(): Called right after the request has been added to the request  
  * list. The function just creates a dynamic copy of raw request data and  
  * attaches it to the request.  
  */  
 /*ARGSUSED*/  
 int  
 rad_proxy(REQUEST *req ARG_UNUSED)  
 {  
         return 0;  
 }  
   
   
 /* ************************************************************************* */  
204  /* Reply functions. Possibly these should go to libclient? */  /* Reply functions. Possibly these should go to libclient? */
205    
206  int  int
207  proxy_send_request(fd, radreq)  proxy_send_request(int fd, RADIUS_REQ *radreq)
         int fd;  
         RADIUS_REQ *radreq;  
208  {  {
209          VALUE_PAIR *plist, *p;          VALUE_PAIR *plist, *p;
210          PROXY_STATE *proxy_state;          PROXY_STATE *proxy_state;
# Line 177  proxy_send_request(fd, radreq) Line 251  proxy_send_request(fd, radreq)
251                    
252          proxy_state = (PROXY_STATE *)p->avp_strvalue;          proxy_state = (PROXY_STATE *)p->avp_strvalue;
253                                
254          proxy_state->ipaddr = get_socket_addr(fd);          proxy_state->ipaddr = radreq->ipaddr; /*FIXME: get_socket_addr(fd);*/
255          proxy_state->id = radreq->id;          proxy_state->id = radreq->id;
256          proxy_state->proxy_id = radreq->server_id;          proxy_state->proxy_id = radreq->server_id;
257          proxy_state->rem_ipaddr = server->addr;          proxy_state->rem_ipaddr = server->addr;
# Line 202  proxy_send_request(fd, radreq) Line 276  proxy_send_request(fd, radreq)
276                  sin.sin_port = htons(                  sin.sin_port = htons(
277                          (radreq->code == RT_AUTHENTICATION_REQUEST) ?                          (radreq->code == RT_AUTHENTICATION_REQUEST) ?
278                          server->port[PORT_AUTH] : server->port[PORT_ACCT]);                          server->port[PORT_AUTH] : server->port[PORT_ACCT]);
279    
280                    debug(1, ("Proxying id %d to %lx",
281                              radreq->id, (u_long)server->addr));
282    
283                  sendto(fd, pdu, size, 0, (struct sockaddr *)&sin, sizeof(sin));                  sendto(fd, pdu, size, 0, (struct sockaddr *)&sin, sizeof(sin));
284          }          }
285          return size;          return size;
286  }  }
287    
288  /* ************************************************************************* */  /* ************************************************************************* */
 /* Functions local to this module */  
   
 static UINT4  
 get_socket_addr(fd)  
         int fd;  
 {  
         struct sockaddr_in sin;  
         int len = sizeof(sin);  
         UINT4 ip = 0;  
   
         /* FIXME: if fd was bound to INADDR_ANY, there is not much sense  
            in doing this. The possible solution will be to use if_nameindex  
            (or SIOCGIFCONF) to get the IP of the first available interface */  
             
         if (getsockname(fd, (struct sockaddr*)&sin, &len) == 0)  
                 ip = sin.sin_addr.s_addr;  
   
         if (ip == INADDR_ANY)  
                 ip = ref_ip;  
         return ip;  
 }  
   
   
 /*  
  *      Decode a password and encode it again.  
  */  
 static void  
 passwd_recode(pass_pair, new_secret, new_vector, req)  
         VALUE_PAIR *pass_pair;  
         char *new_secret;  
         char *new_vector;  
         RADIUS_REQ *req;  
 {  
         char    password[AUTH_STRING_LEN+1];  
         req_decrypt_password(password, req, pass_pair);  
         string_free(pass_pair->avp_strvalue);  
         encrypt_password(pass_pair, password, new_vector, new_secret);  
         /* Don't let the cleantext hang around */  
         memset(password, 0, AUTH_STRING_LEN);  
 }  
   
 /* ************************************************************************* */  
289  /* Interface functions */  /* Interface functions */
290    
291  /* Relay the request to a remote server  /* Relay the request to a remote server
# Line 258  passwd_recode(pass_pair, new_secret, new Line 294  passwd_recode(pass_pair, new_secret, new
294               -1 fail (we don't reply, caller returns without replying) */               -1 fail (we don't reply, caller returns without replying) */
295    
296  int  int
297  proxy_send(radreq, activefd)  proxy_send(REQUEST *req)
         RADIUS_REQ *radreq;  
         int activefd;  
298  {  {
299            RADIUS_REQ *radreq = req->data;
300          int rc;          int rc;
301          char *saved_username;          char *saved_username;
302          char *username;          char *username;
# Line 270  proxy_send(radreq, activefd) Line 305  proxy_send(radreq, activefd)
305          char *realmname;          char *realmname;
306          REALM *realm;          REALM *realm;
307          char *what;          char *what;
308                    RADIUS_UPDATE *upd;
309    
310          /* Look up name. */          /* Look up name. */
311          namepair = avl_find(radreq->request, DA_USER_NAME);          namepair = avl_find(radreq->request, DA_USER_NAME);
312          if (namepair == NULL)          if (namepair == NULL)
# Line 319  proxy_send(radreq, activefd) Line 355  proxy_send(radreq, activefd)
355          radreq->attempt_no = 0;          radreq->attempt_no = 0;
356          radreq->server_id = next_proxy_id(radreq->server->addr);          radreq->server_id = next_proxy_id(radreq->server->addr);
357          radreq->remote_user = string_create(username);          radreq->remote_user = string_create(username);
358    
359            req->update_size = sizeof(*upd) + strlen(realm->realm);
360            upd = emalloc(req->update_size);
361            upd->proxy_id = radreq->server_id;
362            upd->server_no = 0;
363            strcpy(upd->realmname, realm->realm);
364            req->update = upd;
365                    
366          /* If there is no DA_CHAP_CHALLENGE attribute but there          /* If there is no DA_CHAP_CHALLENGE attribute but there
367             is a DA_CHAP_PASSWORD we need to add it since we can't             is a DA_CHAP_PASSWORD we need to add it since we can't
# Line 338  proxy_send(radreq, activefd) Line 381  proxy_send(radreq, activefd)
381                  avl_add_pair(&radreq->request, vp);                  avl_add_pair(&radreq->request, vp);
382          }          }
383    
         /* Now build a new request and send it to the remote radiusd. */  
         proxy_send_request(activefd, radreq);  
           
 #if 1    
         /* And restore username. */  
         string_replace(&namepair->avp_strvalue, saved_username);  
         namepair->avp_strlength = strlen(namepair->avp_strvalue);  
 #endif  
384          efree(saved_username);          efree(saved_username);
385            
386            proxy_send_request(req->fd, radreq);
387            
388          return 1;          return 1;
389  }  }
390    
391    /* FIXME: Unused */
392  void  void
393  proxy_retry(int type, void *data, void *orig_data,  proxy_retry(int type, void *data, void *orig_data,
394              int fd, char *status_str)              int fd, char *status_str)
# Line 383  proxy_retry(int type, void *data, void * Line 421  proxy_retry(int type, void *data, void *
421          namepair->avp_strlength = strlen(namepair->avp_strvalue);          namepair->avp_strlength = strlen(namepair->avp_strvalue);
422  }  }
423    
 /* ************************************************************************* */  
 /* Functions for finding the matching request in the list of outstanding ones.  
  * There appear to be two cases: i) when the remote server retains the  
  * Proxy-State A/V pair, which seems to correspond to RFC 2865,  
  * and ii) when the remote server drops the Proxy-State pair.  
  */  
   
 struct proxy_data {  
         UINT4 ipaddr;  
         PROXY_STATE *state;  
         RADIUS_REQ  *radreq;  
 };  
   
 /* proxy_compare_request(): Find matching request based on the information  
    preserved in the Proxy-State pair. */  
 int  
 proxy_compare_request(void *item, void *datap)  
 {  
         RADIUS_REQ *oldreq = item;  
         struct proxy_data *data = datap;  
   
         debug(10, ("(old=data) id %d %d, ipaddr %#8x %#8x, proxy_id %d %d, server_addr %#8x %#8x",  
                    oldreq->id, data->state->id,  
                    data->ipaddr, data->state->ipaddr,  
                    oldreq->server_id, data->state->proxy_id,  
                    oldreq->server->addr, data->state->rem_ipaddr));  
           
         if (data->state->ipaddr     == data->ipaddr  
             && data->state->id      == oldreq->id  
             && data->state->proxy_id == oldreq->server_id  
             && data->state->rem_ipaddr == oldreq->server->addr)  
                 return 0;  
   
         return 1;  
 }  
   
 /* proxy_compare_request_no_state(): Find matching outstanding request if the  
    server did not retain the Proxy-State pair.  
    miquels@cistron.nl says:  
         Some servers drop the proxy pair. So  
         compare in another way if needed.  
         FIXME: hmmm, perhaps we don't even need Proxy-State  
         after all! */  
 int  
 proxy_compare_request_no_state(void *item, void *datap)  
 {  
         RADIUS_REQ *oldreq = item;  
         struct proxy_data *data = datap;  
           
         debug(10, ("(old=data) id %d %d, ipaddr %#8x %#8x",  
                    oldreq->server_id,  
                    data->radreq->id,  
                    oldreq->server->addr,  
                    data->radreq->ipaddr));  
                           
         if (data->radreq->ipaddr == oldreq->server->addr &&  
             data->radreq->id     == oldreq->server_id)  
                 return 0;  
   
         return 1;  
 }  
   
424    
425  int  int
426  select_allowed(unused, pair)  select_allowed(void *null ARG_UNUSED, VALUE_PAIR *pair)
         void *unused;  
         VALUE_PAIR *pair;  
427  {  {
428          return pair->prop & AP_PROPAGATE;          return pair->prop & AP_PROPAGATE;
429  }  }
# Line 460  select_allowed(unused, pair) Line 434  select_allowed(unused, pair)
434     Return:   0 proxy found     Return:   0 proxy found
435              -1 error don't reply */              -1 error don't reply */
436  int  int
437  proxy_receive(radreq, activefd)  proxy_receive(RADIUS_REQ *radreq, RADIUS_REQ *oldreq, int fd)
         RADIUS_REQ        *radreq;  
         int             activefd;  
438  {  {
439          VALUE_PAIR      *vp, *proxy_state_pair, *prev, *x;          VALUE_PAIR *vp, *proxy_state_pair, *prev, *x;
440          VALUE_PAIR      *allowed_pairs;          VALUE_PAIR *allowed_pairs;
441          RADIUS_REQ      *oldreq;          PROXY_STATE *state;
         PROXY_STATE     *state;  
         struct proxy_data data;  
442                    
443          /* Find the last PROXY_STATE attribute. */          /* Remove the last proxy pair from the list. */
444            /* FIXME: Should be done by proxy_cmp ? */
         oldreq  = NULL;  
445          proxy_state_pair = x = prev = NULL;          proxy_state_pair = x = prev = NULL;
446    
447          for (vp = radreq->request; vp; vp = vp->next) {          for (vp = radreq->request; vp; vp = vp->next) {
# Line 483  proxy_receive(radreq, activefd) Line 452  proxy_receive(radreq, activefd)
452                  x = vp;                  x = vp;
453          }          }
454    
         state = proxy_state_pair ?  
                    (PROXY_STATE *)proxy_state_pair->avp_strvalue : NULL;  
   
         if (state)  
           debug(1, ("state: ipaddr %08x, id %u, proxy_id %u, rem_ipaddr %08x",  
                  state->ipaddr,  
                  state->id,  
                  state->proxy_id,  
                  state->rem_ipaddr));  
   
         /* Find matching request in the list of outstanding requests. */  
         data.ipaddr = get_socket_addr(activefd);  
         data.state = state;  
         data.radreq = radreq;  
           
         debug(1, ("Compare: myip %08x, radreq->id %d, radreq->ipaddr %08x",  
                   data.ipaddr, radreq->id, radreq->ipaddr));  
           
         if (state) {  
                 if (state->proxy_id   == radreq->id &&  
                     state->rem_ipaddr == radreq->ipaddr) {  
                         oldreq = request_scan_list(R_PROXY,  
                                                    proxy_compare_request,  
                                                    &data);  
                 } else {  
                         oldreq = NULL;  
                 }  
         } else {  
                 oldreq = request_scan_list(R_PROXY,  
                                            proxy_compare_request_no_state,  
                                            &data);  
         }  
           
         if (oldreq == NULL) {  
                 char buf[MAX_LONGNAME];  
                 radlog_req(L_PROXY|L_ERR, radreq,  
                            _("Unrecognized proxy reply from server %s, proxy ID %d"),  
                            client_lookup_name(radreq->ipaddr, buf, sizeof buf),  
                            radreq->id);  
                 return -1;  
         }  
   
         /* Remove proxy pair from the list. */  
455          if (proxy_state_pair) {          if (proxy_state_pair) {
456                  if (prev)                  if (prev)
457                          prev->next = proxy_state_pair->next;                          prev->next = proxy_state_pair->next;

Legend:
Removed from v.1.43  
changed lines
  Added in v.1.44

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26