Ejemplo n.º 1
0
Archivo: canl.c Proyecto: CESNET/canl-c
size_t canl_io_write(canl_ctx cc, canl_io_handler io, void *buffer, size_t size, struct timeval *timeout)
{
    io_handler *io_cc = (io_handler*) io;
    glb_ctx *glb_cc = (glb_ctx*) cc;
    int b_written = 0;
    struct canl_mech *mech;

    if (!cc)
        return -1;

    if (!io) {
	set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
	return -1;
    }

    if (io_cc->conn_ctx == NULL)
	return set_error(cc, EINVAL, POSIX_ERROR, "Connection not secured");

    if (!buffer || !size) {
	set_error(cc, EINVAL, POSIX_ERROR, "No memory to read from");
	return -1;
    }

    mech = find_mech(io_cc->oid);

    b_written = mech->write(glb_cc, io_cc, io_cc->conn_ctx,
			    buffer, size, timeout);

    return b_written;
}
Ejemplo n.º 2
0
Archivo: canl.c Proyecto: CESNET/canl-c
/* close connection, preserve some info for the future reuse */
canl_err_code
canl_io_close(canl_ctx cc, canl_io_handler io)
{
    io_handler *io_cc = (io_handler*) io;
    glb_ctx *glb_cc = (glb_ctx*) cc;
    int err = 0;
    canl_mech *mech;

    /*check cc and io*/
    if (!cc) {
        return EINVAL; /* XXX Should rather be a CANL error */
    }

    if (!io)
	return set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");

    if (io_cc->conn_ctx) {
	mech = find_mech(io_cc->oid);
	mech->close(glb_cc, io, io_cc->conn_ctx);
	/* XXX can it be safely reopened ?*/
    }

    if (io_cc->sock != -1) {
        close (io_cc->sock);
        io_cc->sock = -1;
    }

    return err;
}
Ejemplo n.º 3
0
/* return values:
 * 0 - success
 * 1 - failed, try another mechanism
 * -1 - failed, security extensions not supported
 */
int sec_login(const char *host, const char *mech_to_try)
{
	int ret;
	struct sec_client_mech **m;
	void *tmp;

	/* shut up all messages this will produce (they
	 are usually not very user friendly) */
	ftp_set_tmp_verbosity(vbError);

	if(!mech_to_try || strcasecmp(mech_to_try, "none") == 0)
		return 0;

	m = find_mech(mech_to_try);
	if(!m)
		return 1;

	tmp = realloc(ftp->app_data, (*m)->size);
	if (tmp == NULL) {
		ftp_err(_("realloc %zu failed"), (*m)->size);
		return -1;
	}
	ftp->app_data = tmp;

	if ((*m)->init && (*(*m)->init) (ftp->app_data) != 0) {
		printf(_("Skipping %s...\n"), (*m)->name);
		return 1;
	}
	printf(_("Trying %s...\n"), (*m)->name);
	ret = ftp_cmd("AUTH %s", (*m)->name);
	if (ftp->code != ctContinue) {
		if (ret == 504) {
			printf(_("%s is not supported by the server.\n"), (*m)->name);
		} else if (ret == 534) {
			printf(_("%s rejected as security mechanism.\n"), (*m)->name);
		} else if (ftp->code == ctError) {
			printf(_("The server doesn't support the FTP "
					 "security extensions.\n"));
			return -1;
		}
		return 1;
	}

	ret = (*(*m)->auth) (ftp->app_data, host);

	if (ret == AUTH_CONTINUE)
		return 1;
	else if (ret != AUTH_OK) {
		/* mechanism is supposed to output error string */
		return -1;
	}
	ftp->mech = *m;
	ftp->sec_complete = 1;
	ftp->command_prot = prot_safe;

	return *m == NULL;
}
Ejemplo n.º 4
0
Archivo: canl.c Proyecto: CESNET/canl-c
/*TODO select + timeout, EINTR!!! */ 
canl_err_code
canl_io_accept(canl_ctx cc, canl_io_handler io, int new_fd,
        struct sockaddr s_addr, int flags, canl_principal *peer,
        struct timeval *timeout)
{
    int err = 0;
    io_handler *io_cc = (io_handler*) io;
    glb_ctx *glb_cc = (glb_ctx*) cc;
    struct canl_mech *mech = find_mech(GSS_C_NO_OID);
    void *conn_ctx = NULL;

    if (!glb_cc) 
        return EINVAL; /* XXX Should rather be a CANL error */

    if (!io_cc)
        return set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");

    io_cc->sock = new_fd;

    err = mech->server_init(glb_cc, &conn_ctx);
    if (err)
        goto end;

    err = mech->accept(glb_cc, io_cc, conn_ctx, timeout); 
    if (err)
	goto end;

    /* If peer != NULL then client certificate is mandatory*/
      if (peer) {
	err = mech->get_peer(glb_cc, io_cc, conn_ctx, peer);
	if (err)
	    goto end;
    }

    io_cc->conn_ctx = conn_ctx;
    io_cc->oid = GSS_C_NO_OID;

    err = 0;

end:
    if (err) {
        (io_cc)->sock = -1;
        if (conn_ctx)
            mech->finish(glb_cc, conn_ctx);
    }

    return err;
}
Ejemplo n.º 5
0
Archivo: canl.c Proyecto: CESNET/canl-c
static void io_destroy(glb_ctx *cc, io_handler *io)
{
    io_handler *io_cc = (io_handler*) io;
    canl_mech *mech;
    
    if (io == NULL)
	return;

    if (io_cc->conn_ctx) {
	mech = find_mech(io->oid);
	mech->finish(cc, io_cc->conn_ctx);
	io_cc->conn_ctx = NULL;
	io_cc->oid = GSS_C_NO_OID;
    }

    return;
}
Ejemplo n.º 6
0
Archivo: canl.c Proyecto: CESNET/canl-c
void canl_free_ctx(canl_ctx cc)
{
    glb_ctx *ctx = (glb_ctx*) cc;
    struct canl_mech *mech = find_mech(GSS_C_NO_OID);

    if (!cc)
        return;

    /*delete content*/
    if (ctx->err_msg) {
        free(ctx->err_msg);
        ctx->err_msg = NULL;
    }
    /*TODO delete ctx content for real*/
    if (mech)
        mech->free_ctx(ctx);

    if (ctx->err_msg){
        free(ctx->err_msg);
        ctx->err_msg = NULL;
    }
    free(ctx);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
Archivo: canl.c Proyecto: CESNET/canl-c
canl_err_code
canl_io_connect(canl_ctx cc, canl_io_handler io, const char *host, 
        const char *service, int port, gss_OID_set auth_mechs, 
        int flags, canl_principal *peer, struct timeval *timeout)
{
    int err = 0;
    io_handler *io_cc = (io_handler*) io;
    glb_ctx *glb_cc = (glb_ctx*) cc;
    struct _asyn_result ar;
    int i = 0, k;
    int addr_types[] = {AF_INET, AF_INET6}; //TODO ip versions policy?
    int ipver = AF_INET6;
    int j = 0, done;
    struct canl_mech *mech;
    gss_OID oid;

    memset(&ar, 0, sizeof(ar));

    if (!glb_cc) {
        return EINVAL;
    }

    if (!io_cc)
        return set_error(glb_cc, EINVAL, POSIX_ERROR, 
                "IO handler not initialized");

    done = 0;
    for (k = 0; k < sizeof(addr_types)/sizeof(*addr_types); k++) {
        ipver = addr_types[k];
	if (ar.ent) {
	    free_hostent(ar.ent);
	    memset(&ar, 0, sizeof(ar));
	}

        ar.ent = (struct hostent *) calloc (1, sizeof(struct hostent));
        if (ar.ent == NULL)
            return set_error(cc, ENOMEM, POSIX_ERROR, "Not enough memory");

        switch (err = canl_asyn_getservbyname(ipver, &ar, host, NULL)) {
            case NETDB_SUCCESS:
                err = 0;
                break;
            case TRY_AGAIN:
                err = update_error(glb_cc, ETIMEDOUT, POSIX_ERROR,
                        " Timeout reached when connecting to (%s)", host);
		goto end;
            case NETDB_INTERNAL:
		err = update_error(glb_cc, errno, POSIX_ERROR,
                        "Cannot resolve the server hostname (%s)", host);
                continue;
            default:
                err = update_error(glb_cc, err, NETDB_ERROR,
                        "Cannot resolve the server hostname (%s)", host);
                continue;
        }

	j = 0;
	do {
	    if (auth_mechs == GSS_C_NO_OID_SET || auth_mechs->count == 0)
		oid = GSS_C_NO_OID;
	    else
		oid = &auth_mechs->elements[j];

	    mech = find_mech(oid);

	    err = 0;
	    for (i = 0; ar.ent->h_addr_list[i]; i++) {
		void *ctx = NULL;

		if (err == ETIMEDOUT)
		    goto end;

		err = try_connect(glb_cc, io_cc, ar.ent->h_addr_list[i], 
			ar.ent->h_addrtype, port, timeout);//TODO timeout
		if (err)
		    continue;

		err = mech->client_init(glb_cc, &ctx);
		if (err) {
		    canl_io_close(glb_cc, io_cc);
		    continue;
		}

		err = mech->connect(glb_cc, io_cc, ctx, timeout, host);
		if (err) {
		    canl_io_close(glb_cc, io_cc);
		    mech->finish(glb_cc, ctx);
		    ctx = NULL;
                    continue;
                }
                io_cc->conn_ctx = ctx;
                done = 1;
                /* If peer != NULL then client certificate is mandatory*/
                if (peer) {
                    err = mech->get_peer(glb_cc, io_cc, ctx, peer);
                    if (err)
                        goto end;
                }
                
                break;
	    }
	    if (err == ETIMEDOUT)
		goto end;
	    j++;
	} while (auth_mechs != GSS_C_NO_OID_SET && j < auth_mechs->count && !done);

        free_hostent(ar.ent);
        ar.ent = NULL;
	if (done)
	    break;
    }

    if (!done) {
	err = ECONNREFUSED;
	goto end;
    }

    err = 0;

end:
    if (err) /* XXX: rather invent own error */
	err = update_error(glb_cc, ECONNREFUSED, POSIX_ERROR,
		"Failed to make network connection to server %s", host);

    if (ar.ent != NULL)
        free_hostent(ar.ent);

    return err;
}