/**
* 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;
}