예제 #1
0
void
gss_verr(int exitval, int status, const char *fmt, va_list ap)
{
/*     vwarnx (fmt, ap); */
    gss_print_errors (status);
/*     exit (exitval); */
}
예제 #2
0
int
eDestroy(int fd)
{

	OM_uint32       maj_stat, min_stat;
	tunnel_ctx_t* tunnel_ctx = getGssContext(fd);
	if( tunnel_ctx == NULL ) {
		return -1;
	}

	maj_stat = gss_delete_sec_context(&min_stat,  &tunnel_ctx->context_hdl, GSS_C_NO_BUFFER);
	destroyGssContext(fd);

#if defined(GSIGSS) &&  defined(GLOBUS_BUG)
	/* work arount globus bug */
	(void) globus_module_deactivate(GLOBUS_GSI_GSSAPI_MODULE);
#endif /* GLOBUS_BUG */


	if( maj_stat != GSS_S_COMPLETE ) {
		gss_print_errors(maj_stat);
		return -1;
	}

	return 0;
}
예제 #3
0
ssize_t
eWrite(int fd, const void *buf, size_t size)
{
	ssize_t  ret = -1;

	gss_buffer_desc enc_buff, data_buf;
	OM_uint32 maj_stat, min_stat;

	int             len;
	char           *str = NULL;
	static const char prefix[] = "enc ";
	static const char nl = '\n';

	tunnel_ctx_t* tunnel_ctx = getGssContext(fd);
	if( tunnel_ctx == NULL ) {
		return -1;
	}

	if(tunnel_ctx->isAuthentificated) {

		data_buf.value = (void *)buf;
		data_buf.length = size;

		maj_stat = gss_wrap(&min_stat, tunnel_ctx->context_hdl, 1, GSS_C_QOP_DEFAULT,
						&data_buf, NULL, &enc_buff);


		if (GSS_ERROR(maj_stat)) {
			gss_print_errors(maj_stat);
		}

	}else{
		enc_buff.value = (void *)buf;
		enc_buff.length = size;
	}


	len = base64_encode(enc_buff.value, enc_buff.length, &str);

	if(tunnel_ctx->isAuthentificated){
		gss_release_buffer(&min_stat, &enc_buff);
	}

	if( writen(fd, prefix, 4) != 4) {
            goto clean_exit;
        }

	if (writen(fd, str, len) != len) {
            goto clean_exit;
        }

        if( writen(fd, &nl, 1) != 1) {
            goto clean_exit;
        }

        ret = size;
clean_exit:
	free(str);
	return ret;
}
예제 #4
0
static void
gss_err(int exitval, int status, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    vwarnx (fmt, args);
    gss_print_errors (status);
    va_end(args);
    exit (exitval);
}
예제 #5
0
static int
import_name(const char *kname, const char *host, gss_name_t * target_name)
{
	OM_uint32       maj_stat, min_stat;
	gss_buffer_desc name;

	name.length = asprintf((char **) &name.value, "%s@%s", kname, host);
	maj_stat = gss_import_name(&min_stat,
				   &name,
#ifdef MIT_KRB5
				   gss_nt_service_name,
#else				/* heimdal */
				   GSS_C_NT_HOSTBASED_SERVICE,
#endif				/* MIT_KRB5 */
				   target_name);
	if (GSS_ERROR(maj_stat)) {
		gss_print_errors(maj_stat);
		return -1;
	}
	free(name.value);
	return 0;
}
예제 #6
0
static int delete_sec_context(char *buf, int index, ei_x_buff *presult)
{
    ei_x_buff result = *presult;

    /*
      {delete_sec_context, Idx} -> {ok, }
    */

    long idx;
    OM_uint32 maj_stat, min_stat;
	
    EI(ei_decode_long(buf, &index, &idx));

    if (idx < 0 || idx >= MAX_SESSIONS || !g_sessions[idx] ||
	g_sessions[idx] == GSS_C_NO_CONTEXT)
	ENCODE_ERROR("bad_instance");

    maj_stat = gss_delete_sec_context(&min_stat, &g_sessions[idx],
				      GSS_C_NO_BUFFER);

    g_sessions[idx] = NULL;

    if (!GSS_ERROR(maj_stat)) {
	EI(ei_x_encode_atom(&result, "ok") ||
	   ei_x_encode_atom(&result, "done")
	    );
    } else {
	fprintf(stderr, "gss_delete_sec_context: %08x", maj_stat);
	gss_print_errors(min_stat);
	EI(ei_x_encode_atom(&result, "error") || ei_x_encode_long(&result, maj_stat));
    }

error:
    *presult = result;
    return 0;
}
예제 #7
0
파일: http_client.c 프로젝트: aosm/Heimdal
int
main(int argc, char **argv)
{
    int i, s, done, print_body, gssapi_done, gssapi_started, optidx = 0;
    const char *host, *page;
    struct http_req req;
    char *headers[99]; /* XXX */
    int num_headers;
    krb5_storage *sp;

    gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL;
    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
    gss_name_t server = GSS_C_NO_NAME;
    gss_OID mech_oid, cred_mech_oid;
    OM_uint32 flags;
    OM_uint32 maj_stat, min_stat;

    setprogname(argv[0]);

    if(getarg(http_args, num_http_args, argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    mech_oid = select_mech(mech);

    if (cred_mech_str)
	cred_mech_oid = select_mech(cred_mech_str);
    else
	cred_mech_oid = mech_oid;

    if (argc != 1 && argc != 2)
	errx(1, "usage: %s host [page]", getprogname());
    host = argv[0];
    if (argc == 2)
	page = argv[1];
    else
	page = "/";

    flags = 0;
    if (delegate_flag)
	flags |= GSS_C_DELEG_FLAG;
    if (policy_flag)
	flags |= GSS_C_DELEG_POLICY_FLAG;
    if (mutual_flag)
	flags |= GSS_C_MUTUAL_FLAG;

    done = 0;
    num_headers = 0;
    gssapi_done = 0;
    gssapi_started = 0;

    if (client_str) {
	gss_buffer_desc name_buffer;
	gss_name_t name;
	gss_OID_set mechset = GSS_C_NO_OID_SET;

	name_buffer.value = client_str;
	name_buffer.length = strlen(client_str);

	maj_stat = gss_import_name(&min_stat, &name_buffer, GSS_C_NT_USER_NAME, &name);
	if (maj_stat)
	    errx(1, "failed to import name");

	if (cred_mech_oid) {
	    gss_create_empty_oid_set(&min_stat, &mechset);
	    gss_add_oid_set_member(&min_stat, cred_mech_oid, &mechset);
	}
	
	maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE,
				    mechset, GSS_C_INITIATE,
				    &client_cred, NULL, NULL);
	gss_release_name(&min_stat, &name);
	gss_release_oid_set(&min_stat, &mechset);
	if (maj_stat)
	    errx(1, "failed to find cred of name %s", client_str);
    }

    {
	gss_buffer_desc name_token;
	char *name;
	asprintf(&name, "%s@%s", gss_service, host);
	name_token.length = strlen(name);
	name_token.value = name;
	
	maj_stat = gss_import_name(&min_stat,
				   &name_token,
				   GSS_C_NT_HOSTBASED_SERVICE,
				   &server);
	if (GSS_ERROR(maj_stat))
	    gss_err (1, min_stat, "gss_inport_name: %s", name);
	free(name);
    }

    s = do_connect(host, port_str);
    if (s < 0)
	errx(1, "connection failed");

    sp = krb5_storage_from_fd(s);
    if (sp == NULL)
	errx(1, "krb5_storage_from_fd");

    do {
	print_body = 0;

	http_query(sp, host, page, headers, num_headers, &req);
	for (i = 0 ; i < num_headers; i++)
	    free(headers[i]);
	num_headers = 0;

	if (strstr(req.response, " 200 ") != NULL) {
	    print_body = 1;
	    done = 1;
	} else if (strstr(req.response, " 401 ") != NULL) {
	    if (http_find_header(&req, "WWW-Authenticate:") == NULL)
		errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
	}

	if (!gssapi_done) {
	    const char *h = http_find_header(&req, "WWW-Authenticate:");
	    if (h == NULL)
		errx(1, "Got %s but missed `WWW-Authenticate'", req.response);

	    if (strncasecmp(h, "Negotiate", 9) == 0) {
		gss_buffer_desc input_token, output_token;

		if (verbose_flag)
		    printf("Negotiate found\n");

		i = 9;
		while(h[i] && isspace((unsigned char)h[i]))
		    i++;
		if (h[i] != '\0') {
		    size_t len = strlen(&h[i]);
		    int slen;
		    if (len == 0)
			errx(1, "invalid Negotiate token");
		    input_token.value = emalloc(len);
		    slen = base64_decode(&h[i], input_token.value);
		    if (slen < 0)
			errx(1, "invalid base64 Negotiate token %s", &h[i]);
		    input_token.length = slen;
		} else {
		    if (gssapi_started)
			errx(1, "Negotiate already started");
		    gssapi_started = 1;

		    input_token.length = 0;
		    input_token.value = NULL;
		}

		if (strstr(req.response, " 200 ") != NULL)
		    sleep(1);

		maj_stat =
		    gss_init_sec_context(&min_stat,
					 client_cred,
					 &context_hdl,
					 server,
					 mech_oid,
					 flags,
					 0,
					 GSS_C_NO_CHANNEL_BINDINGS,
					 &input_token,
					 NULL,
					 &output_token,
					 NULL,
					 NULL);
		if (maj_stat == GSS_S_CONTINUE_NEEDED) {

		} else if (maj_stat == GSS_S_COMPLETE) {
		    gss_name_t targ_name, src_name;
		    gss_buffer_desc name_buffer;
		    gss_OID mech_type;

		    gssapi_done = 1;

		    maj_stat = gss_inquire_context(&min_stat,
						   context_hdl,
						   &src_name,
						   &targ_name,
						   NULL,
						   &mech_type,
						   NULL,
						   NULL,
						   NULL);
		    if (GSS_ERROR(maj_stat))
			gss_err (1, min_stat, "gss_inquire_context");

		    printf("Negotiate done: %s\n", mech);

		    maj_stat = gss_display_name(&min_stat,
						src_name,
						&name_buffer,
						NULL);
		    if (GSS_ERROR(maj_stat))
			gss_print_errors(min_stat);
		    else
			printf("Source: %.*s\n",
			       (int)name_buffer.length,
			       (char *)name_buffer.value);

		    gss_release_buffer(&min_stat, &name_buffer);

		    maj_stat = gss_display_name(&min_stat,
						targ_name,
						&name_buffer,
						NULL);
		    if (GSS_ERROR(maj_stat))
			gss_print_errors(min_stat);
		    else
			printf("Target: %.*s\n",
			       (int)name_buffer.length,
			       (char *)name_buffer.value);

		    gss_release_name(&min_stat, &targ_name);
		    gss_release_buffer(&min_stat, &name_buffer);
		} else {
		    gss_err (1, min_stat, "gss_init_sec_context");
		}


		if (output_token.length) {
		    char *neg_token;

		    base64_encode(output_token.value,
				  (int)output_token.length,
				  &neg_token);

		    asprintf(&headers[0], "Authorization: Negotiate %s",
			     neg_token);

		    num_headers = 1;
		    free(neg_token);
		    gss_release_buffer(&min_stat, &output_token);
		}
		if (input_token.length)
		    free(input_token.value);

	    } else
		done = 1;
	} else
	    done = 1;

	if (print_body || verbose_flag)
	    printf("%.*s\n", (int)req.body_size, (char *)req.body);

	http_req_free(&req);
    } while (!done);

    if (gssapi_done == 0)
	errx(1, "gssapi not done but http dance done");

    krb5_storage_free(sp);
    close(s);

    return 0;
}
예제 #8
0
static int 
accept_user(gss_ctx_id_t *ctx,
	    gss_buffer_desc *in,
	    gss_buffer_desc *out,
	    gss_buffer_desc *name,
	    char **pccname)
{
    OM_uint32 maj_stat, min_stat;
    gss_name_t src_name = GSS_C_NO_NAME;
    gss_OID oid = GSS_C_NO_OID;
    int ret = -1;
    gss_cred_id_t delegated_cred_handle = NULL;

    *pccname = NULL;
    maj_stat = gss_accept_sec_context(&min_stat,
				      ctx,
				      GSS_C_NO_CREDENTIAL,
				      in,
				      GSS_C_NO_CHANNEL_BINDINGS,
				      &src_name,
				      &oid,
				      out,
				      NULL,
				      NULL,
				      &delegated_cred_handle);

    if ((maj_stat & GSS_S_CONTINUE_NEEDED) || maj_stat != GSS_S_COMPLETE) {
	fprintf(stderr, "gss_accept_sec_context: %08x %d %d ",
		maj_stat, maj_stat & GSS_S_CONTINUE_NEEDED, maj_stat != GSS_S_COMPLETE);
	gss_print_errors(min_stat);
	ret = HTTP_UNAUTHORIZED;
	goto out;
    }
				      
    if (name) {
	/* Use display name */
	maj_stat = gss_display_name(&min_stat, src_name, name, NULL);
	if (maj_stat != GSS_S_COMPLETE) {
	    ret = HTTP_UNAUTHORIZED;
	    goto out;
	}
    }

    ret = OK;

    if (delegated_cred_handle) {
	const struct mech_specific *m;

	m = find_mech(oid);
	if (m && m->save_cred)
	    (*m->save_cred)(name->value, delegated_cred_handle, pccname);
    } else {
/* 	fprintf(stderr, "Not delegated\r\n"); */
    }

 out:
    if (src_name != GSS_C_NO_NAME)
	gss_release_name(&min_stat, &src_name);

    return ret;
}
예제 #9
0
ssize_t
eRead(int fd, void *buf, size_t size)
{
	char            line[MAXBUF];
	char            c;
	int             i;
	int             len;

	static char            *data;
	static int             pos = 0;
	static int             used = 0;

	tunnel_ctx_t* tunnel_ctx = getGssContext(fd);
	if( tunnel_ctx == NULL ) {
		return -1;
	}

	gss_buffer_desc enc_buff, data_buf;
	OM_uint32 maj_stat, min_stat;

	if( pos == used ) {

		if(data == NULL) {
			data = malloc(MAXBUF);
		}


		i = 0;
		do {
			len = read(fd, &c, 1);

			if( len < 0 ) {
				return -1;
			}

			if( len != 0 ) {
				line[i] = c;
				i++;
			}

		} while ( (i < MAXBUF -1) && (c != '\n') && (c != '\r') && (len > 0) );


		line[i] = '\0';

		if (i > 0) {

			if(tunnel_ctx->isAuthentificated) {

				enc_buff.value = malloc(i);
				enc_buff.length = base64_decode(line + 4, enc_buff.value);

				maj_stat = gss_unwrap(&min_stat, tunnel_ctx->context_hdl,
								&enc_buff, &data_buf, NULL, NULL);


				if (GSS_ERROR(maj_stat)) {
					gss_print_errors(maj_stat);
				}


				memcpy(data, data_buf.value, data_buf.length);
				gss_release_buffer(&min_stat, &enc_buff);
			}else{
				data_buf.length =  base64_decode(line + 4, data);
			}


			used = data_buf.length;
			pos = 0;
			if(tunnel_ctx->isAuthentificated){
				gss_release_buffer(&min_stat, &data_buf);
			}

		} else {

			return -1;
		}


	}


	if( size > used - pos) {
		len = used - pos ;
	}else{
		len = size;
	}

	memcpy(buf, data+pos, len);
	pos +=len;
	return len;

}
예제 #10
0
int
gss_check(int sock)
{
	struct sockaddr_in remote, local;
	socklen_t       addrlen;
	char           *name;

	gss_buffer_desc input_token, output_token;
	gss_cred_id_t   delegated_cred_handle = GSS_C_NO_CREDENTIAL;
	OM_uint32       maj_stat, min_stat;
	gss_name_t      client_name;
	gss_buffer_desc export_name;
	gss_channel_bindings_t input_chan_bindings;

	tunnel_ctx_t* tunnel_ctx = createGssContext(sock);
	if( tunnel_ctx == NULL ) {
		return -1;
	}

#ifndef MIT_KRB5
# if 0 /*VP This does not work neither with GT4 nor Heimdal */
	delegated_cred_handle = malloc(sizeof(*delegated_cred_handle));
	memset((char *) delegated_cred_handle, 0,
	       sizeof(*delegated_cred_handle));
# endif
#endif	/* ! MIT_KRB5 */


	addrlen = sizeof(local);
	if (getsockname(sock, (struct sockaddr *) & local, &addrlen) < 0
	    || addrlen != sizeof(local)) {
#ifdef SHOW_ERROR
		perror("getsockname");
#endif
		return -1;
	}
	addrlen = sizeof(remote);
	if (getpeername(sock, (struct sockaddr *) & remote, &addrlen) < 0
	    || addrlen != sizeof(remote)) {
#ifdef SHOW_ERROR
		perror("getpeername");
#endif
		return -1;
	}
	input_chan_bindings = malloc(sizeof(struct gss_channel_bindings_struct));

	sockaddr_to_gss_address((struct sockaddr *) & local,
				&input_chan_bindings->initiator_addrtype,
				&input_chan_bindings->initiator_address);
	sockaddr_to_gss_address((struct sockaddr *) & remote,
				&input_chan_bindings->acceptor_addrtype,
				&input_chan_bindings->acceptor_address);

	input_chan_bindings->application_data.length = 0;
	input_chan_bindings->application_data.value = NULL;

	do {

		input_token.value = malloc(MAXBUF);
		input_token.length = eRead(sock, input_token.value, MAXBUF);

		maj_stat = gss_accept_sec_context(&min_stat,
						  &tunnel_ctx->context_hdl,
						  GSS_C_NO_CREDENTIAL,
						  &input_token,
						  input_chan_bindings,
						  &client_name,
						  NULL,
						  &output_token,
						  NULL,
						  NULL,
						  &delegated_cred_handle);

		if (GSS_ERROR(maj_stat)) {
			gss_print_errors(maj_stat);
		}

		gss_release_buffer(&min_stat, &input_token);

		if (output_token.length != 0) {
			eWrite(sock, output_token.value, output_token.length);
			printf("sended token %d\n", output_token.length);
			gss_release_buffer(&min_stat, &output_token);
		}

		if (maj_stat == GSS_S_COMPLETE) {
			printf("GSS OK\n");
			if (GSS_ERROR(maj_stat)) {
				gss_print_errors(maj_stat);
			}
			maj_stat = gss_export_name(&min_stat, client_name, &export_name);

			if (GSS_ERROR(maj_stat)) {
				gss_print_errors(maj_stat);
			}
			name = realloc(export_name.value, export_name.length + 1);
			name[export_name.length] = '\0';
#if 0
			printf("name = %s\n", name); fflush(stdout);
#endif
		}




	} while( maj_stat == GSS_S_CONTINUE_NEEDED ) ;

	return 0;
}
예제 #11
0
int
gssAuth(int sock, tunnel_ctx_t* tunnel_ctx, const char *hostname, const char *service)
{
	struct sockaddr_in6 remote, local;
	socklen_t       addrlen;

	gss_buffer_desc real_input_token, real_output_token;
	gss_buffer_t    input_token = &real_input_token, output_token = &real_output_token;
	OM_uint32       maj_stat, min_stat;
	gss_name_t      server = GSS_C_NO_NAME;
	gss_channel_bindings_t input_chan_bindings;



	if (import_name(service, hostname, &server) < 0) {
		return -1;
	}
	addrlen = sizeof(local);
	if (getsockname(sock, (struct sockaddr *) & local, &addrlen) < 0
	    || addrlen > sizeof(local)) {
#ifdef SHOW_ERROR
		perror("sockname");
#endif
		return -1;
	}
	addrlen = sizeof(remote);
	if (getpeername(sock, (struct sockaddr *) & remote, &addrlen) < 0
	    || addrlen > sizeof(remote)) {
#ifdef SHOW_ERROR
		perror("getpeer");
#endif
		return -1;
	}
	input_token->length = 0;
	input_token->value = NULL;

	output_token->length = 0;
	output_token->value = NULL;

#ifdef GSIGSS
	input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
#else
	input_chan_bindings = malloc(sizeof(struct gss_channel_bindings_struct));

	sockaddr_to_gss_address((struct sockaddr *) & local,
				&input_chan_bindings->initiator_addrtype,
				&input_chan_bindings->initiator_address);
	sockaddr_to_gss_address((struct sockaddr *) & remote,
				&input_chan_bindings->acceptor_addrtype,
				&input_chan_bindings->acceptor_address);

	input_chan_bindings->application_data.length = 0;
	input_chan_bindings->application_data.value = NULL;
#endif
	while (!tunnel_ctx->isAuthentificated) {
		maj_stat =
			gss_init_sec_context(&min_stat,
					     GSS_C_NO_CREDENTIAL,
					     &tunnel_ctx->context_hdl,
					     server,
					     GSS_C_NO_OID,
				     	 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
					     0,
					     input_chan_bindings,
					     input_token,
					     NULL,
					     output_token,
					     NULL,
					     NULL);

		if (tunnel_ctx->context_hdl == NULL) {
			gss_print_errors(min_stat);
			/* send a waste to the server */
			eWrite(sock, "123", 3);
			return -1;
		}
		if ((maj_stat != GSS_S_CONTINUE_NEEDED) && (maj_stat != GSS_S_COMPLETE)) {
			gss_print_errors(min_stat);
			/* send a waste to the server */
			eWrite(sock, "123", 3);
			return -1;
		}
		if (output_token->length > 0) {
			eWrite(sock, output_token->value, output_token->length);
			gss_release_buffer(&min_stat, output_token);
		}
		if (maj_stat & GSS_S_CONTINUE_NEEDED) {
			if( input_token->value == NULL ) {
				input_token->value = malloc(MAXBUF);
			}

            if( input_token->value == NULL ) {
                return -1;
            }

			input_token->length = eRead(sock, input_token->value, MAXBUF);
			if( (input_token->length < 0 ) || (input_token->length > MAXBUF) ) {
				/* incorrect length */
				free(input_token->value);
				input_token->value = NULL;
				return -1;
			}
		} else {
			tunnel_ctx->isAuthentificated = 1;
		}

	}

	return 1;
}