366 lines
9.0 KiB
C
366 lines
9.0 KiB
C
/*
|
|
* idpc - IDP as a C CGI program
|
|
* Copyright (C) 2004 Entr'ouvert
|
|
*
|
|
* Author: Frederic Peters <fpeters@entrouvert.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "idpc.h"
|
|
|
|
/* the Single Sign On service URL handles several profiles:
|
|
* 1. Liberty Artifact (fig2, page20)
|
|
* 2. Browser POST (fig3, page26)
|
|
* 3. Liberty-Enabled Client and Proxy (fig5, page30) (SOAP request)
|
|
*/
|
|
|
|
int lecp_profile(LassoServer *server)
|
|
{
|
|
char *soap_msg;
|
|
int clen = 0;
|
|
int req_type;
|
|
LassoLecp *lecp;
|
|
char *user_dump, *session_dump;
|
|
int rc;
|
|
struct authentication *auth;
|
|
char *user_id;
|
|
char *reauth_time;
|
|
|
|
clen = atoi(getenv("CONTENT_LENGTH"));
|
|
soap_msg = malloc(clen+1);
|
|
soap_msg[clen] = 0;
|
|
fgets(soap_msg, clen+1, stdin);
|
|
req_type = lasso_profile_get_request_type_from_soap_msg(soap_msg);
|
|
if (req_type != lassoRequestTypeLecp) {
|
|
return error_page("soap but req type not LECP");
|
|
}
|
|
|
|
auth = get_authentication(
|
|
get_config_string("//idpc:authenticationMethod"));
|
|
if (auth == NULL) {
|
|
return error_page("Wrong authentication");
|
|
}
|
|
|
|
user_id = auth->auth_function();
|
|
|
|
if (user_id == NULL) {
|
|
/* anyway */
|
|
return error_page("Error authenticating");
|
|
}
|
|
|
|
/* retrieve user_dump and session_dump */
|
|
rc = db_get_dumps(user_id, &user_dump, &session_dump);
|
|
if (rc) {
|
|
return error_page("Error getting dumps from db");
|
|
}
|
|
|
|
lecp = lasso_lecp_new(server);
|
|
|
|
rc = set_profile_from_dumps(LASSO_PROFILE(lecp),
|
|
user_dump, session_dump);
|
|
free(user_dump);
|
|
free(session_dump);
|
|
if (rc) {
|
|
lasso_lecp_destroy(lecp);
|
|
return error_page("Failed to set profile from dumps");
|
|
}
|
|
|
|
|
|
|
|
rc = lasso_lecp_init_from_authn_request_msg(lecp, soap_msg,
|
|
lassoHttpMethodSoap);
|
|
if (!rc) {
|
|
lasso_lecp_destroy(lecp);
|
|
return error_page("lecp init failed");
|
|
}
|
|
|
|
reauth_time = strtime(time(NULL) +
|
|
(get_config_string("//idpc:reauthenticationDelay") ?
|
|
atoi(get_config_string("//idpc:reauthenticationDelay")) : 7200));
|
|
rc = lasso_lecp_build_authn_response_envelope_msg(
|
|
lecp, 1, auth->lasso_name,
|
|
reauth_time);
|
|
free(reauth_time);
|
|
if (!rc) {
|
|
lasso_lecp_destroy(lecp);
|
|
return error_page("build authn resp failed");
|
|
}
|
|
|
|
printf("Content-Type: application/vnd.liberty-response+xml\n");
|
|
printf("Liberty-Enabled: urn:liberty:iff:2003-08 http://projectliberty.org/specs/v1\n");
|
|
printf("Cache-Control: no-cache\n");
|
|
printf("Pragma: no-cache\n");
|
|
printf("\n");
|
|
printf(LASSO_PROFILE(lecp)->msg_body);
|
|
|
|
lasso_lecp_destroy(lecp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int artifact_profile(LassoLogin *login, char *user_id, struct authentication *auth)
|
|
{
|
|
int rc;
|
|
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int single_sign_on()
|
|
{
|
|
LassoServer *server;
|
|
LassoLogin *login;
|
|
lassoHttpMethod response_method;
|
|
char *http_verb, *ct;
|
|
char *authn_request_msg = NULL;
|
|
int rc;
|
|
char *user_id;
|
|
char *user_dump, *session_dump;
|
|
struct authentication *auth;
|
|
int i = 0;
|
|
char *reauth_time;
|
|
|
|
|
|
http_verb = getenv("REQUEST_METHOD");
|
|
if (http_verb == NULL) {
|
|
return error_page("No HTTP verb");
|
|
}
|
|
|
|
ct = getenv("CONTENT_TYPE");
|
|
|
|
if (strcmp(http_verb, "GET") == 0) {
|
|
char *t;
|
|
|
|
t = getenv("QUERY_STRING");
|
|
if (t) {
|
|
authn_request_msg = strdup(t);
|
|
} else {
|
|
authn_request_msg = strdup("");
|
|
}
|
|
response_method = lassoHttpMethodRedirect;
|
|
}
|
|
|
|
if (strcmp(http_verb, "POST") == 0) {
|
|
if (strcmp(ct, "multipart/form-data") == 0) {
|
|
/* example in the spec use x-www-form-urlencoded;
|
|
* don't know if multipart/form-data must be supported
|
|
*/
|
|
return error_page("multipart not supported");
|
|
}
|
|
if (strcmp(ct, "application/x-www-form-urlencoded") == 0) {
|
|
int clen;
|
|
char *msg;
|
|
char **res;
|
|
|
|
clen = atoi(getenv("CONTENT_LENGTH"));
|
|
msg = malloc(clen+1);
|
|
msg[clen] = 0;
|
|
fgets(msg, clen+1, stdin);
|
|
response_method = lassoHttpMethodPost;
|
|
|
|
res = urlencoded_to_strings(msg);
|
|
for (i=0; res[i]; i++) {
|
|
if (strncmp(res[i], "LAREQ=", 6) == 0) {
|
|
authn_request_msg = strdup(res[i]+6);
|
|
}
|
|
free(res[i]);
|
|
}
|
|
free(res);
|
|
free(msg);
|
|
}
|
|
}
|
|
|
|
server = get_config_server();
|
|
if (server == NULL) {
|
|
return error_page("Failed to get server configuration");
|
|
}
|
|
|
|
if (strcmp(http_verb, "POST") == 0 && strcmp(ct, "text/xml") == 0) {
|
|
rc = lecp_profile(server);
|
|
lasso_server_destroy(server);
|
|
return rc;
|
|
}
|
|
|
|
|
|
if (authn_request_msg == NULL) {
|
|
lasso_server_destroy(server);
|
|
return error_page("failed to get authn_request_msg");
|
|
}
|
|
|
|
/* get user_id; it is the key to retrieve previous user_dump and
|
|
* session_dump */
|
|
auth = get_authentication(
|
|
get_config_string("//idpc:authenticationMethod"));
|
|
if (auth == NULL) {
|
|
lasso_server_destroy(server);
|
|
return error_page("Wrong authentication");
|
|
}
|
|
|
|
user_id = auth->auth_function();
|
|
|
|
if (user_id == NULL) {
|
|
/* anyway */
|
|
lasso_server_destroy(server);
|
|
return error_page("Error authenticating");
|
|
}
|
|
|
|
/* retrieve user_dump and session_dump */
|
|
rc = db_get_dumps(user_id, &user_dump, &session_dump);
|
|
if (rc) {
|
|
lasso_server_destroy(server);
|
|
return error_page("Error getting dumps from db");
|
|
}
|
|
|
|
login = lasso_login_new(server);
|
|
|
|
rc = set_profile_from_dumps(LASSO_PROFILE(login),
|
|
user_dump, session_dump);
|
|
free(user_dump);
|
|
free(session_dump);
|
|
if (rc) {
|
|
lasso_server_destroy(server);
|
|
lasso_login_destroy(login);
|
|
return error_page("Failed to set profile from dumps");
|
|
}
|
|
|
|
rc = lasso_login_init_from_authn_request_msg(login,
|
|
authn_request_msg, response_method);
|
|
if (rc) {
|
|
char msg[100];
|
|
sprintf(msg, "Lasso login error, %d", rc);
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page(msg);
|
|
}
|
|
|
|
|
|
rc = lasso_login_must_authenticate(login);
|
|
if (rc == 1 && user_id == NULL) {
|
|
/* must authenticate and user_id was NULL; bad (an
|
|
* authentication scheme not handled by Apache could be
|
|
* inserted here)
|
|
*/
|
|
}
|
|
|
|
reauth_time = strtime(time(NULL) +
|
|
(get_config_string("//idpc:reauthenticationDelay") ?
|
|
atoi(get_config_string("//idpc:reauthenticationDelay")) : 7200));
|
|
|
|
if (login->protocolProfile == lassoLoginProtocolProfileBrwsArt) {
|
|
rc = lasso_login_build_artifact_msg(login,
|
|
1, /* user authenticated */
|
|
auth->lasso_name,
|
|
reauth_time,
|
|
lassoHttpMethodRedirect);
|
|
if (rc) {
|
|
free(reauth_time);
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page("build_artifact_msg failed");
|
|
}
|
|
} else {
|
|
/* POST profile (lassoLoginProtocolProfileBrwsPost) */
|
|
rc = lasso_login_build_authn_response_msg(login,
|
|
1, /* user authenticated */
|
|
auth->lasso_name,
|
|
reauth_time);
|
|
if (rc) {
|
|
free(reauth_time);
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page("build_authn_response_msg failed");
|
|
}
|
|
}
|
|
free(reauth_time);
|
|
|
|
rc = db_save_name_identifier(
|
|
LASSO_PROFILE(login)->nameIdentifier, user_id);
|
|
if (rc) {
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page("failed to save name identifier");
|
|
}
|
|
|
|
rc = save_profile_dumps(LASSO_PROFILE(login));
|
|
if (rc) {
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page("failed to save dumps");
|
|
}
|
|
|
|
|
|
if (login->protocolProfile == lassoLoginProtocolProfileBrwsArt) {
|
|
rc = db_save_assertion(
|
|
login->assertionArtifact,
|
|
login->response_dump);
|
|
if (rc) {
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
return error_page("failed to save assertion");
|
|
}
|
|
printf("Location: %s\n\nRedirected", LASSO_PROFILE(login)->msg_url);
|
|
} else {
|
|
/* POST profile (lassoLoginProtocolProfileBrwsPost) */
|
|
printf("Content-type: text/html\n\n");
|
|
printf("<html><head><title>Authentication Response</title></head>\n"
|
|
"<body onload=\"document.forms[0].submit()\">\n"
|
|
" <form action=\"%s\" method=\"post\">\n"
|
|
" <p>You should be automaticaly redirected to your"
|
|
" service provider.</p>\n"
|
|
" <p>If this page is still visible after a few seconds,\n"
|
|
" press the <em>Send</em> button below.</p>\n"
|
|
" <input type=\"hidden\" name=\"LARES\" value=\"%s\"/>\n"
|
|
" <input type=\"submit\" />\n"
|
|
" </form>\n"
|
|
"</body></html>",
|
|
LASSO_PROFILE(login)->msg_url,
|
|
LASSO_PROFILE(login)->msg_body);
|
|
}
|
|
|
|
lasso_login_destroy(login);
|
|
lasso_server_destroy(server);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int rc;
|
|
|
|
if (argc > 1 && handle_args(argc, argv) ) {
|
|
return 0;
|
|
}
|
|
|
|
rc = init_config();
|
|
if (rc != 0) {
|
|
return error_page("Failed to init configuration");
|
|
}
|
|
lasso_init();
|
|
rc = db_init();
|
|
if (rc != 0) {
|
|
error_page("Failed to init database access");
|
|
goto shutdown;
|
|
}
|
|
rc = single_sign_on();
|
|
shutdown:
|
|
db_finish();
|
|
lasso_shutdown();
|
|
return rc;
|
|
}
|
|
|