/** * auth.c * * Copyright (C) 2005 - 2008 Bojan Smojver, Rexursive * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * */ #include #ifdef HAVE_RXV_SPIN_H #include #endif #ifdef HAVE_HTTP_LOG_H #include #endif int rxv_spin_service(rxv_spin_ctx_t *ctx){ request_rec *r=rxv_spin_r(ctx),*ar; apreq_handle_t *req=rxv_spin_req(ctx); apreq_param_t *user_p,*pass_p,*ret_p; char *auth_URI; const char *user,*pass,*ret; /* just process the template as normal if username/password not there */ if(!((user_p=apreq_param(req,"spin_username")) && (pass_p=apreq_param(req,"spin_password")))){ /* if we had a failure before, put that into context */ rxv_spin_set(ctx,"auth_failed",rxv_spin_ses_get(ctx,"auth_failed")); /* if we have auth_return from before, finish */ if(rxv_spin_ses_sget(ctx,"auth_return")) return OK; /* pick up the return URL, if any */ if((ret_p=apreq_param(req,"return"))){ ret=ret_p->v.data; } else{ /* if we don't have the return URL, bomb out */ ap_log_rerror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,r,"auth: no return URL"); return HTTP_INTERNAL_SERVER_ERROR; } /* store return URL for later */ rxv_spin_ses_sset(ctx,"auth_return",ret); return OK; } /* if we have nowhere to return, bomb out */ if(!(ret=rxv_spin_ses_sget(ctx,"auth_return"))){ ap_log_rerror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,r,"auth: no return URL"); return HTTP_INTERNAL_SERVER_ERROR; } /* once here, we don't need return URL in the session any more */ rxv_spin_ses_del(ctx,"auth_return"); /* if no authentication URI, bomb out too */ if(!(auth_URI=rxv_spin_app_sget(ctx,"auth_URI"))){ ap_log_rerror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,r, "auth: no authentication URI"); return HTTP_INTERNAL_SERVER_ERROR; } /* if not proper URI, bomb out as well */ if(auth_URI[0]!='/'){ ap_log_rerror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,r, "auth: invalid auth_URI, has to start with '/'"); return HTTP_INTERNAL_SERVER_ERROR; } /* create a subrequest for authentication */ if(!(ar=ap_sub_req_lookup_uri(auth_URI,r,r->output_filters))){ ap_log_rerror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,r, "auth: cannot create subrequest"); return HTTP_INTERNAL_SERVER_ERROR; } /* make sure we didn't fail in a bad way */ if(ap_is_HTTP_SERVER_ERROR(ar->status)){ ap_log_rerror(APLOG_MARK,APLOG_ERR,ar->status,r, "auth: fatal subrequest processing error"); ap_destroy_sub_req(ar); return ar->status; } user=user_p->v.data; pass=pass_p->v.data; /* add the credentials to the request */ apr_table_add(ar->headers_in,"Authorization", apr_pstrcat(ar->pool,"Basic ", ap_pbase64encode(ar->pool, apr_pstrcat(ar->pool,user,":",pass,NULL)),NULL)); /* if authentication fails, delete auth_user in session store */ if(ap_process_request_internal(ar)==OK){ rxv_spin_ses_sset(ctx,"auth_user",user); rxv_spin_ses_sset(ctx,"auth_time", apr_psprintf(r->pool, "%" APR_TIME_T_FMT,apr_time_now())); rxv_spin_ses_del(ctx,"auth_failed"); } else{ rxv_spin_ses_del(ctx,"auth_user"); rxv_spin_ses_del(ctx,"auth_time"); rxv_spin_ses_sset(ctx,"auth_failed",""); } /* clean up the subrequest */ ap_destroy_sub_req(ar); /* return to the caller */ apr_table_add(r->err_headers_out,"Location",ret); return HTTP_SEE_OTHER; }