/*
* Copyright 2001 by Lionel Schwarz, Computing Center IN2P3
*
*/
#include <stdio.h>
#include "gfw-misc.h"
#include "gfw.h"
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif
/*extern int verbose;*/
/*
* Function: gfw_client_auth
*
* Purpose: authenticate a client on a remote server for a specific service
*
* Arguments:
*
* is (r) the input stream socket
* os (r) the
* service_name (r) the GSS-API service name to authenticate to
* logmessage (w) the message written int case of failure
*
* Returns: 0 on success, -1 on failure
*
* Effects:
*
* gfw_client_auth establishes a GSS-API context with service_name
* over the connection designated by the two sockets.
* -1 is returned if any step fails, otherwise 0 is returned.
*/
int gfw_client_auth(int is, int os, char *service_name, char *logmessage)
{
gss_ctx_id_t gss_context;
OM_uint32 ret_flags;
OM_uint32 maj_stat, min_stat;
size_t i;
gss_buffer_desc send_tok, recv_tok, *token_ptr;
gss_name_t target_name;
OM_uint32 deleg_flag=0;
gss_OID oid = GSS_C_NULL_OID;
gss_name_t src_name, targ_name;
gss_buffer_desc sname, tname;
gss_buffer_desc client_name, xmit_buf, logon_buf;
OM_uint32 lifetime;
gss_OID mechanism, name_type;
int is_local;
OM_uint32 context_flags;
int is_open;
char *userid;
int conf_state=0;
display_file = stdout;
#ifdef DEBUG
printf("Entering gfw-client...\n");
#endif
/*
* Import the name into target_name. Use send_tok to save
* local variable space.
*/
send_tok.value = service_name;
send_tok.length = strlen(service_name) + 1;
maj_stat = gss_import_name(&min_stat, &send_tok,
(gss_OID) gss_nt_service_name, &target_name);
if (maj_stat != GSS_S_COMPLETE) {
status_to_string(maj_stat, logmessage);
display_status("parsing name", maj_stat, min_stat);
return -1;
}
/*
* Perform the context-establishement loop.
*
*/
token_ptr = GSS_C_NO_BUFFER;
gss_context = GSS_C_NO_CONTEXT;
do {
maj_stat =
gss_init_sec_context(&min_stat,
GSS_C_NO_CREDENTIAL,
&gss_context,
target_name,
oid,
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | deleg_flag,
0,
NULL, /* no channel bindings */
token_ptr,
NULL, /* ignore mech type */
&send_tok,
&ret_flags,
NULL); /* ignore time_rec */
if (token_ptr != GSS_C_NO_BUFFER)
(void) gss_release_buffer(&min_stat, &recv_tok);
if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
status_to_string(maj_stat, logmessage);
display_status("initializing context", maj_stat, min_stat);
(void) gss_release_name(&min_stat, &target_name);
return -1;
}
if (send_tok.length != 0) {
#ifdef DEBUG
fprintf(stdout, "sending token...\n");
#endif
if (send_token(os, &send_tok) < 0) {
strcpy(logmessage, "Error while sending token");
(void) gss_release_buffer(&min_stat, &send_tok);
(void) gss_release_name(&min_stat, &target_name);
return -1;
}
#ifdef DEBUG
fprintf(stdout, "token sent (size=%d)\n",send_tok.length);
#endif
}
(void) gss_release_buffer(&min_stat, &send_tok);
if (maj_stat == GSS_S_CONTINUE_NEEDED) {
#ifdef DEBUG
fprintf(stdout, "receiving token...\n");
#endif
if (recv_token(is, &recv_tok) < 0) {
strcpy(logmessage, "Error while receiving token");
(void) gss_release_name(&min_stat, &target_name);
return -1;
}
token_ptr = &recv_tok;
#ifdef DEBUG
fprintf(stdout, "token received (size=%d)\n",recv_tok.length);
#endif
}
} while (maj_stat & GSS_S_CONTINUE_NEEDED);
#ifdef DEBUG
fprintf(stdout, "COMPLETE\n");
#endif
(void) gss_release_name(&min_stat, &target_name);
(void) gss_delete_sec_context(&min_stat, &gss_context, GSS_C_NO_BUFFER);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1