/*@-incondefs@*/ /* _et_list is global on unix but not in header annotations */
errcode_t KRB5_CALLCONV
add_error_table(/*@dependent@*/ const struct error_table * et)
/*@modifies _et_list,et_list_dynamic@*/
/*@=incondefs@*/
{
    struct dynamic_et_list *del;
    int merr;

    if (CALL_INIT_FUNCTION(com_err_initialize))
        return 0;

    del = (struct dynamic_et_list *)malloc(sizeof(struct dynamic_et_list));
    if (del == NULL)
        return ENOMEM;

    del->table = et;

    merr = k5_mutex_lock(&et_list_lock);
    if (merr) {
        free(del);
        return merr;
    }
    del->next = et_list_dynamic;
    et_list_dynamic = del;
    return k5_mutex_unlock(&et_list_lock);
}
예제 #2
0
errcode_t KRB5_CALLCONV
add_error_table(const struct error_table *et)
{
    struct et_list *e;

    if (CALL_INIT_FUNCTION(com_err_initialize))
        return 0;

    e = malloc(sizeof(struct et_list));
    if (e == NULL)
        return ENOMEM;

    e->table = et;

    k5_mutex_lock(&et_list_lock);
    e->next = et_list;
    et_list = e;

    /* If there are two strings at the end of the table, they are a text domain
     * and locale dir, and we are supposed to call bindtextdomain. */
    if (et->msgs[et->n_msgs] != NULL && et->msgs[et->n_msgs + 1] != NULL)
        bindtextdomain(et->msgs[et->n_msgs], et->msgs[et->n_msgs + 1]);

    k5_mutex_unlock(&et_list_lock);
    return 0;
}
예제 #3
0
파일: threads.c 프로젝트: WeiY/krb5
void *k5_getspecific (k5_key_t keynum)
{
    struct tsd_block *t;
    int err;

    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
    if (err)
        return NULL;

    assert(keynum >= 0 && keynum < K5_KEY_MAX);
    assert(destructors_set[keynum] == 1);

#ifndef ENABLE_THREADS

    t = &tsd_no_threads;

#elif defined(_WIN32)

    t = TlsGetValue(tls_idx);

#else /* POSIX */

    if (K5_PTHREADS_LOADED)
        t = pthread_getspecific(key);
    else
        t = GET_NO_PTHREAD_TSD();

#endif

    if (t == NULL)
        return NULL;
    return t->values[keynum];
}
/*@-incondefs@*/ /* _et_list is global on unix but not in header annotations */
errcode_t KRB5_CALLCONV
remove_error_table(const struct error_table * et)
/*@modifies _et_list,et_list_dynamic@*/
/*@=incondefs@*/
{
    struct dynamic_et_list **del;
    struct et_list **el;
    int merr;

    if (CALL_INIT_FUNCTION(com_err_initialize))
        return 0;
    merr = k5_mutex_lock(&et_list_lock);
    if (merr)
        return merr;

    /* Remove the entry that matches the error table instance.  Prefer dynamic
       entries, but if there are none, check for a static one too.  */
    for (del = &et_list_dynamic; *del; del = &(*del)->next)
        if ((*del)->table == et) {
            /*@only@*/ struct dynamic_et_list *old = *del;
            *del = old->next;
            free (old);
            return k5_mutex_unlock(&et_list_lock);
        }
    for (el = &_et_list; *el; el = &(*el)->next)
        if ((*el)->table == et) {
            struct et_list *old = *el;
            *el = old->next;
            old->next = NULL;
            old->table = NULL;
            return k5_mutex_unlock(&et_list_lock);
        }
    k5_mutex_unlock(&et_list_lock);
    return ENOENT;
}
예제 #5
0
파일: kdb5.c 프로젝트: aosm/Kerberos
static int
kdb_lock_list()
{
    int err;
    err = CALL_INIT_FUNCTION (kdb_init_lock_list);
    if (err)
	return err;
    return k5_mutex_lock(&db_lock);
}
예제 #6
0
kim_error kim_os_library_unlock_for_bundle_lookup (void)
{
    kim_error err = CALL_INIT_FUNCTION (kim_os_library_thread_init);

    if (!err) {
        err = k5_mutex_unlock (&g_bundle_lookup_mutex);
    }

    return err;
}
예제 #7
0
파일: threads.c 프로젝트: aosm/Kerberos
int k5_key_register (k5_key_t keynum, void (*destructor)(void *))
{
    int err;

    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
    if (err)
	return err;

    assert(keynum >= 0 && keynum < K5_KEY_MAX);

#ifndef ENABLE_THREADS

    assert(destructors_set[keynum] == 0);
    destructors[keynum] = destructor;
    destructors_set[keynum] = 1;
    err = 0;

#elif defined(_WIN32)

    /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK.  */
    EnterCriticalSection(&key_lock);
    assert(destructors_set[keynum] == 0);
    destructors_set[keynum] = 1;
    destructors[keynum] = destructor;
    LeaveCriticalSection(&key_lock);
    err = 0;

#else /* POSIX */

    err = k5_mutex_lock(&key_lock);
    if (err == 0) {
	assert(destructors_set[keynum] == 0);
	destructors_set[keynum] = 1;
	destructors[keynum] = destructor;
	err = k5_mutex_unlock(&key_lock);
    }

#endif
    return 0;
}
예제 #8
0
파일: threads.c 프로젝트: WeiY/krb5
void krb5int_thread_detach_hook (void)
{
    /* XXX Memory leak here!
       Need to destroy all TLS objects we know about for this thread.  */
    struct tsd_block *t;
    int i, err;

    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
    if (err)
        return;

    t = TlsGetValue(tls_idx);
    if (t == NULL)
        return;
    for (i = 0; i < K5_KEY_MAX; i++) {
        if (destructors_set[i] && destructors[i] && t->values[i]) {
            void *v = t->values[i];
            t->values[i] = 0;
            (*destructors[i])(v);
        }
    }
}
예제 #9
0
errcode_t KRB5_CALLCONV
remove_error_table(const struct error_table *et)
{
    struct et_list **ep, *e;

    if (CALL_INIT_FUNCTION(com_err_initialize))
        return 0;
    k5_mutex_lock(&et_list_lock);

    /* Remove the entry that matches the error table instance. */
    for (ep = &et_list; *ep; ep = &(*ep)->next) {
        if ((*ep)->table == et) {
            e = *ep;
            *ep = e->next;
            free(e);
            k5_mutex_unlock(&et_list_lock);
            return 0;
        }
    }
    k5_mutex_unlock(&et_list_lock);
    return ENOENT;
}
예제 #10
0
kern_return_t k5_ipc_client_reply (mach_port_t             in_reply_port,
                                   k5_ipc_inl_reply_t      in_inl_reply,
                                   mach_msg_type_number_t  in_inl_replyCnt,
                                   k5_ipc_ool_reply_t      in_ool_reply,
                                   mach_msg_type_number_t  in_ool_replyCnt)
{
    kern_return_t err = KERN_SUCCESS;
    k5_ipc_connection_info cinfo = NULL;
    
    if (!err) {
        err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init);
    }
    
    if (!err) {
        cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO);
        if (!cinfo || !cinfo->reply_stream) { err = EINVAL; }
    }
    
    if (!err) {
        if (in_inl_replyCnt) {
            err = k5_ipc_stream_write (cinfo->reply_stream, 
                                       in_inl_reply, in_inl_replyCnt);
            
        } else if (in_ool_replyCnt) {
            err = k5_ipc_stream_write (cinfo->reply_stream, 
                                       in_ool_reply, in_ool_replyCnt);
            
        } else {
            err = EINVAL;
        }
    }
    
    if (in_ool_replyCnt) { vm_deallocate (mach_task_self (), 
                                          (vm_address_t) in_ool_reply, 
                                          in_ool_replyCnt); }
    
    return err;
}
예제 #11
0
static boolean_t k5_ipc_reply_demux (mach_msg_header_t *request, 
                                     mach_msg_header_t *reply) 
{
    boolean_t handled = 0;
    
    if (CALL_INIT_FUNCTION (k5_cli_ipc_thread_init) != 0) {
        return 0;
    }    
    
    if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
        k5_ipc_connection_info cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO);
        if (cinfo) { 
            cinfo->server_died = 1;
        }
        
        handled = 1; /* server died */
    }
    
    if (!handled) {
        handled = k5_ipc_reply_server (request, reply);
    }
    
    return handled;    
}
예제 #12
0
int krb5int_crypto_init(void)
{
    return CALL_INIT_FUNCTION(cryptoint_initialize_library);
}
예제 #13
0
errcode_t profile_open_file(const_profile_filespec_t filespec,
			    prf_file_t *ret_prof)
{
	prf_file_t	prf;
	errcode_t	retval;
	char		*home_env = 0;
	prf_data_t	data;
	char		*expanded_filename;

	retval = CALL_INIT_FUNCTION(profile_library_initializer);
	if (retval)
		return retval;

	scan_shared_trees_unlocked();

	prf = malloc(sizeof(struct _prf_file_t));
	if (!prf)
		return ENOMEM;
	memset(prf, 0, sizeof(struct _prf_file_t));
	prf->magic = PROF_MAGIC_FILE;

	if (filespec[0] == '~' && filespec[1] == '/') {
		home_env = getenv("HOME");
#ifdef HAVE_PWD_H
		if (home_env == NULL) {
		    uid_t uid;
		    struct passwd *pw, pwx;
		    char pwbuf[BUFSIZ];

		    uid = getuid();
		    if (!k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw)
			&& pw != NULL && pw->pw_dir[0] != 0)
			home_env = pw->pw_dir;
		}
#endif
	}
	if (home_env) {
	    if (asprintf(&expanded_filename, "%s%s", home_env,
			 filespec + 1) < 0)
		expanded_filename = 0;
	} else
	    expanded_filename = strdup(filespec);
	if (expanded_filename == 0) {
	    free(prf);
	    return ENOMEM;
	}

	retval = k5_mutex_lock(&g_shared_trees_mutex);
	if (retval) {
	    free(expanded_filename);
	    free(prf);
	    scan_shared_trees_unlocked();
	    return retval;
	}
	scan_shared_trees_locked();
	for (data = g_shared_trees; data; data = data->next) {
	    if (!strcmp(data->filespec, expanded_filename)
		/* Check that current uid has read access.  */
		&& r_access(data->filespec))
		break;
	}
	if (data) {
	    data->refcount++;
	    (void) k5_mutex_unlock(&g_shared_trees_mutex);
	    retval = profile_update_file_data(data);
	    free(expanded_filename);
	    prf->data = data;
	    *ret_prof = prf;
	    scan_shared_trees_unlocked();
	    return retval;
	}
	(void) k5_mutex_unlock(&g_shared_trees_mutex);
	data = profile_make_prf_data(expanded_filename);
	if (data == NULL) {
	    free(prf);
	    free(expanded_filename);
	    return ENOMEM;
	}
	free(expanded_filename);
	prf->data = data;

	retval = k5_mutex_init(&data->lock);
	if (retval) {
	    free(data);
	    free(prf);
	    return retval;
	}

	retval = profile_update_file(prf);
	if (retval) {
		profile_close_file(prf);
		return retval;
	}

	retval = k5_mutex_lock(&g_shared_trees_mutex);
	if (retval) {
	    profile_close_file(prf);
	    scan_shared_trees_unlocked();
	    return retval;
	}
	scan_shared_trees_locked();
	data->flags |= PROFILE_FILE_SHARED;
	data->next = g_shared_trees;
	g_shared_trees = data;
	scan_shared_trees_locked();
	(void) k5_mutex_unlock(&g_shared_trees_mutex);

	*ret_prof = prf;
	return 0;
}
int com_err_finish_init()
{
    return CALL_INIT_FUNCTION(com_err_initialize);
}
예제 #15
0
/* Always-delayed initialization -- error table linkage, etc.  */
krb5_error_code krb5int_initialize_library (void)
{
    return CALL_INIT_FUNCTION(krb5int_lib_init);
}
예제 #16
0
파일: threads.c 프로젝트: WeiY/krb5
int krb5int_call_thread_support_init (void)
{
    return CALL_INIT_FUNCTION(krb5int_thread_support_init);
}
예제 #17
0
int32_t k5_ipc_send_request (const char    *in_service_id,
                             int32_t        in_launch_server,
                             k5_ipc_stream  in_request_stream,
                             k5_ipc_stream *out_reply_stream)
{
    int err = 0;
    int32_t done = 0;
    int32_t try_count = 0;
    mach_port_t server_port = MACH_PORT_NULL;
    k5_ipc_connection_info cinfo = NULL;
    k5_ipc_connection connection = NULL;
    mach_port_t reply_port = MACH_PORT_NULL;
    const char *inl_request = NULL; /* char * so we can pass the buffer in directly */
    mach_msg_type_number_t inl_request_length = 0;
    k5_ipc_ool_request_t ool_request = NULL;
    mach_msg_type_number_t ool_request_length = 0;

    if (!in_request_stream) { err = EINVAL; }
    if (!out_reply_stream ) { err = EINVAL; }
    
    if (!err) {
        err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init);
    }    
    
    if (!err) {
        /* depending on how big the message is, use the fast inline buffer or  
         * the slow dynamically allocated buffer */
        mach_msg_type_number_t request_length = k5_ipc_stream_size (in_request_stream);
        
        if (request_length > K5_IPC_MAX_INL_MSG_SIZE) {
            /*dprintf ("%s choosing out of line buffer (size is %d)", 
             *                  __FUNCTION__, request_length); */
            
            err = vm_read (mach_task_self (), 
                           (vm_address_t) k5_ipc_stream_data (in_request_stream), 
                           request_length, 
                           (vm_address_t *) &ool_request, 
                           &ool_request_length);        
        } else {
            /*dprintf ("%s choosing in line buffer (size is %d)",
             *                  __FUNCTION__, request_length); */
            
            inl_request_length = request_length;
            inl_request = k5_ipc_stream_data (in_request_stream);
        }
    }

    if (!err) {
        cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO);

        if (!cinfo) {
            err = k5_ipc_client_cinfo_allocate (&cinfo);

            if (!err) {
                err = k5_setspecific (K5_KEY_IPC_CONNECTION_INFO, cinfo);
            }
        }
        
        if (!err) {
            int i, found = 0;

            for (i = 0; i < KIPC_SERVICE_COUNT; i++) {
                if (!strcmp (in_service_id, cinfo->connections[i].service_id)) {
                    found = 1;
                    connection = &cinfo->connections[i];
                    break;
                }
            }
            
            if (!found) { err = EINVAL; }
        }
    }
    
    if (!err) {
        err = k5_ipc_client_lookup_server (in_service_id, in_launch_server, 
                                           TRUE, &server_port);
    }

    if (!err) {
        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, 
                                  &reply_port);
    }
    
    while (!err && !done) {
        if (!err && !MACH_PORT_VALID (connection->port)) {
            err = k5_ipc_client_create_client_connection (server_port, 
                                                          &connection->port);
        }
        
        if (!err) {
            err = k5_ipc_client_request (connection->port, reply_port,
                                         inl_request, inl_request_length,
                                         ool_request, ool_request_length);
            
        }
        
        if (err == MACH_SEND_INVALID_DEST) {
            if (try_count < 2) { 
                try_count++;
                err = 0;
            }

            if (MACH_PORT_VALID (connection->port)) {
                mach_port_mod_refs (mach_task_self(), connection->port, 
                                    MACH_PORT_RIGHT_SEND, -1 );
                connection->port = MACH_PORT_NULL;
            }    
            
            /* Look up server name again without using the cached copy */
            err = k5_ipc_client_lookup_server (in_service_id,  
                                               in_launch_server, 
                                               FALSE, &server_port);
            
        } else {
            /* Talked to server, though we may have gotten an error */
            done = 1;
            
            /* Because we use ",dealloc" ool_request will be freed by mach. 
            * Don't double free it. */
            ool_request = NULL; 
            ool_request_length = 0;                
        }            
    }
    
    if (!err) {
        err = k5_ipc_stream_new (&cinfo->reply_stream);
    }
    
    if (!err) {
        mach_port_t old_notification_target = MACH_PORT_NULL;

        /* request no-senders notification so we know when server dies */
        err = mach_port_request_notification (mach_task_self (), reply_port, 
                                              MACH_NOTIFY_NO_SENDERS, 1, 
                                              reply_port, 
                                              MACH_MSG_TYPE_MAKE_SEND_ONCE, 
                                              &old_notification_target);
        
        if (!err && old_notification_target != MACH_PORT_NULL) {
            mach_port_deallocate (mach_task_self (), old_notification_target);
        }
    }
    
    if (!err) {
        cinfo->server_died = 0;
        
        err = mach_msg_server_once (k5_ipc_reply_demux, K5_IPC_MAX_MSG_SIZE, 
                                    reply_port, MACH_MSG_TIMEOUT_NONE);
        
        if (!err && cinfo->server_died) {
            err = ENOTCONN;
        }
    }
    
    if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
        err = 0;  /* If server is not running just return an empty stream. */
    }
    
    if (!err) {
        *out_reply_stream = cinfo->reply_stream;
        cinfo->reply_stream = NULL;
    }
 
    if (reply_port != MACH_PORT_NULL) { 
        mach_port_destroy (mach_task_self (), reply_port); 
    }
    if (ool_request_length) { 
        vm_deallocate (mach_task_self (), 
                       (vm_address_t) ool_request, ool_request_length); 
    }
    if (cinfo && cinfo->reply_stream) { 
        k5_ipc_stream_release (cinfo->reply_stream); 
        cinfo->reply_stream = NULL;
    }
    
    return err;    
}
예제 #18
0
파일: threads.c 프로젝트: WeiY/krb5
int k5_setspecific (k5_key_t keynum, void *value)
{
    struct tsd_block *t;
    int err;

    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
    if (err)
        return err;

    assert(keynum >= 0 && keynum < K5_KEY_MAX);
    assert(destructors_set[keynum] == 1);

#ifndef ENABLE_THREADS

    t = &tsd_no_threads;

#elif defined(_WIN32)

    t = TlsGetValue(tls_idx);
    if (t == NULL) {
        int i;
        t = malloc(sizeof(*t));
        if (t == NULL)
            return ENOMEM;
        for (i = 0; i < K5_KEY_MAX; i++)
            t->values[i] = 0;
        /* add to global linked list */
        /*      t->next = 0; */
        err = TlsSetValue(tls_idx, t);
        if (!err) {
            free(t);
            return GetLastError();
        }
    }

#else /* POSIX */

    if (K5_PTHREADS_LOADED) {
        t = pthread_getspecific(key);
        if (t == NULL) {
            int i;
            t = malloc(sizeof(*t));
            if (t == NULL)
                return ENOMEM;
            for (i = 0; i < K5_KEY_MAX; i++)
                t->values[i] = 0;
            /* add to global linked list */
            t->next = 0;
            err = pthread_setspecific(key, t);
            if (err) {
                free(t);
                return err;
            }
        }
    } else {
        t = GET_NO_PTHREAD_TSD();
    }

#endif

    t->values[keynum] = value;
    return 0;
}
예제 #19
0
int
gssint_mechglue_initialize_library(void)
{
	return CALL_INIT_FUNCTION(gssint_mechglue_init);
}
const char * KRB5_CALLCONV
error_message(long code)
/*@modifies internalState@*/
{
    unsigned long offset;
    unsigned long l_offset;
    struct et_list *et;
    struct dynamic_et_list *det;
    unsigned long table_num;
    int started = 0;
    unsigned int divisor = 100;
    char *cp, *cp1;
    const struct error_table *table;
    int merr;

    l_offset = (unsigned long)code & ((1<<ERRCODE_RANGE)-1);
    offset = l_offset;
    table_num = ((unsigned long)code - l_offset) & ERRCODE_MAX;
    if (table_num == 0
#ifdef __sgi
        /* Irix 6.5 uses a much bigger table than other UNIX
           systems I've looked at, but the table is sparse.  The
           sparse entries start around 500, but sys_nerr is only
           152.  */
        || (code > 0 && code <= 1600)
#endif
    ) {
        if (code == 0)
            goto oops;

        /* This could trip if int is 16 bits.  */
        if ((unsigned long)(int)code != (unsigned long)code)
            abort ();
#ifdef HAVE_STRERROR_R
        cp = get_thread_buffer();
        if (cp && strerror_r((int) code, cp, ET_EBUFSIZ) == 0)
            return cp;
#endif
#ifdef HAVE_STRERROR
        cp = strerror((int) code);
        if (cp)
            return cp;
#elif defined HAVE_SYS_ERRLIST
        if (offset < sys_nerr)
            return(sys_errlist[offset]);
#endif
        goto oops;
    }

    if (CALL_INIT_FUNCTION(com_err_initialize))
        return 0;
    merr = k5_mutex_lock(&et_list_lock);
    if (merr)
        goto oops;
    dprintf (("scanning static list for %x\n", table_num));
    for (et = _et_list; et != NULL; et = et->next) {
        if (et->table == NULL)
            continue;
        dprintf (("\t%x = %s\n", et->table->base & ERRCODE_MAX,
                  et->table->msgs[0]));
        if ((et->table->base & ERRCODE_MAX) == table_num) {
            table = et->table;
            goto found;
        }
    }
    dprintf (("scanning dynamic list for %x\n", table_num));
    for (det = et_list_dynamic; det != NULL; det = det->next) {
        dprintf (("\t%x = %s\n", det->table->base & ERRCODE_MAX,
                  det->table->msgs[0]));
        if ((det->table->base & ERRCODE_MAX) == table_num) {
            table = det->table;
            goto found;
        }
    }
    goto no_table_found;

found:
    k5_mutex_unlock(&et_list_lock);
    dprintf (("found it!\n"));
    /* This is the right table */

    /* This could trip if int is 16 bits.  */
    if ((unsigned long)(unsigned int)offset != offset)
        goto no_table_found;

    if (table->n_msgs <= (unsigned int) offset)
        goto no_table_found;

    return table->msgs[offset];

no_table_found:
    k5_mutex_unlock(&et_list_lock);
#if defined(_WIN32)
    /*
     * WinSock errors exist in the 10000 and 11000 ranges
     * but might not appear if WinSock is not initialized
     */
    if (code >= WSABASEERR && code < WSABASEERR + 1100) {
        table_num = 0;
        offset = code;
        divisor = WSABASEERR;
    }
#endif
#ifdef _WIN32
    {
        LPVOID msgbuf;

        if (! FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                             NULL /* lpSource */,
                             (DWORD) code,
                             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                             (LPTSTR) &msgbuf,
                             (DWORD) 0 /*sizeof(buffer)*/,
                             NULL /* va_list */ )) {
            /*
             * WinSock errors exist in the 10000 and 11000 ranges
             * but might not appear if WinSock is not initialized
             */
            if (code >= WSABASEERR && code < WSABASEERR + 1100) {
                table_num = 0;
                offset = code;
                divisor = 10000;
            }

            goto oops;
        } else {
            char *buffer;
            cp = get_thread_buffer();
            if (cp == NULL)
                return "Unknown error code";
            buffer = cp;
            strncpy(buffer, msgbuf, ET_EBUFSIZ);
            buffer[ET_EBUFSIZ-1] = '\0';
            cp = buffer + strlen(buffer) - 1;
            if (*cp == '\n') *cp-- = '\0';
            if (*cp == '\r') *cp-- = '\0';
            if (*cp == '.') *cp-- = '\0';

            LocalFree(msgbuf);
            return buffer;
        }
    }
#endif

oops:

    cp = get_thread_buffer();
    if (cp == NULL)
        return "Unknown error code";
    cp1 = cp;
    strlcpy(cp, "Unknown code ", ET_EBUFSIZ);
    cp += sizeof("Unknown code ") - 1;
    if (table_num != 0L) {
        (void) error_table_name_r(table_num, cp);
        while (*cp != '\0')
            cp++;
        *cp++ = ' ';
    }
    while (divisor > 1) {
        if (started != 0 || offset >= divisor) {
            *cp++ = '0' + offset / divisor;
            offset %= divisor;
            started++;
        }
        divisor /= 10;
    }
    *cp++ = '0' + offset;
    *cp = '\0';
    return(cp1);
}
예제 #21
0
파일: py-locate.c 프로젝트: Akasurde/krb5
static krb5_error_code
lookup(void *blob, enum locate_service_type svc, const char *realm,
       int socktype, int family,
       int (*cbfunc)(void *, int, struct sockaddr *), void *cbdata)
{
    PyObject *py_result, *svcarg, *realmarg, *arglist;
    int listsize, i, x;
    struct addrinfo aihints, *airesult;
    int thissocktype;

//    fprintf(stderr, "%s:%d: lookup(%d,%s,%d,%d)\n", F, __LINE__,
//          svc, realm, socktype, family);
    sctx = blob;                /* XXX: Not thread safe!  */
    i = CALL_INIT_FUNCTION (my_init);
    if (i) {
#if 0
        fprintf(stderr, "%s:%d: module initialization failed\n", F, __LINE__);
#endif
        return i;
    }
    if (locatefn == 0)
        return KRB5_PLUGIN_NO_HANDLE;
    svcarg = PyInt_FromLong (svc);
    /* error? */
    realmarg = PyString_FromString ((char *) realm);
    /* error? */
    arglist = PyTuple_New (4);
    /* error? */

    PyTuple_SetItem (arglist, 0, svcarg);
    PyTuple_SetItem (arglist, 1, realmarg);
    PyTuple_SetItem (arglist, 2, PyInt_FromLong (socktype));
    PyTuple_SetItem (arglist, 3, PyInt_FromLong (family));
    /* references handed off, no decref */

    py_result = PyObject_CallObject (locatefn, arglist);
    Py_DECREF (arglist);
    if (PyErr_Occurred()) {
        fprintf(stderr,"%s:%d: python error\n", F, __LINE__);
        PyErr_Print();
        krb5_set_error_message(blob, -1,
                               "Python evaluation error, see stderr");
        return -1;
    }
    if (py_result == 0) {
        fprintf(stderr, "%s:%d: returned null object\n", F, __LINE__);
        return -1;
    }
    if (py_result == Py_False)
        return KRB5_PLUGIN_NO_HANDLE;
    if (! PyList_Check (py_result)) {
        Py_DECREF (py_result);
        fprintf(stderr, "%s:%d: returned non-list, non-False\n", F, __LINE__);
        krb5_set_error_message(blob, -1,
                               "Python script error -- returned non-list, non-False result");
        return -1;
    }
    listsize = PyList_Size (py_result);
    /* allocate */
    memset(&aihints, 0, sizeof(aihints));
    aihints.ai_flags = AI_NUMERICHOST;
    aihints.ai_family = family;
    for (i = 0; i < listsize; i++) {
        PyObject *answer, *field;
        char *hoststr, *portstr, portbuf[3*sizeof(long) + 4];
        int cbret;

        answer = PyList_GetItem (py_result, i);
        if (! PyTuple_Check (answer)) {
            krb5_set_error_message(blob, -1,
                                   "Python script error -- returned item %d not a tuple", i);
            /* leak?  */
            return -1;
        }
        if (PyTuple_Size (answer) != 3) {
            krb5_set_error_message(blob, -1,
                                   "Python script error -- returned tuple %d size %d should be 3",
                                   i, PyTuple_Size (answer));
            /* leak?  */
            return -1;
        }
        field = PyTuple_GetItem (answer, 0);
        if (! PyString_Check (field)) {
            /* leak?  */
            krb5_set_error_message(blob, -1,
                                   "Python script error -- first component of tuple %d is not a string",
                                   i);
            return -1;
        }
        hoststr = PyString_AsString (field);
        field = PyTuple_GetItem (answer, 1);
        if (PyString_Check (field)) {
            portstr = PyString_AsString (field);
        } else if (PyInt_Check (field)) {
            snprintf(portbuf, sizeof(portbuf), "%ld", PyInt_AsLong (field));
            portstr = portbuf;
        } else {
            krb5_set_error_message(blob, -1,
                                   "Python script error -- second component of tuple %d neither a string nor an integer",
                                   i);
            /* leak?  */
            return -1;
        }
        field = PyTuple_GetItem (answer, 2);
        if (! PyInt_Check (field)) {
            krb5_set_error_message(blob, -1,
                                   "Python script error -- third component of tuple %d not an integer",
                                   i);
            /* leak?  */
            return -1;
        }
        thissocktype = PyInt_AsLong (field);
        switch (thissocktype) {
        case SOCK_STREAM:
        case SOCK_DGRAM:
            /* okay */
            if (socktype != 0 && socktype != thissocktype) {
                krb5_set_error_message(blob, -1,
                                       "Python script error -- tuple %d has socket type %d, should only have %d",
                                       i, thissocktype, socktype);
                /* leak?  */
                return -1;
            }
            break;
        default:
            /* 0 is not acceptable */
            krb5_set_error_message(blob, -1,
                                   "Python script error -- tuple %d has invalid socket type %d",
                                   i, thissocktype);
            /* leak?  */
            return -1;
        }
        aihints.ai_socktype = thissocktype;
        aihints.ai_flags = AI_ADDRCONFIG;
        x = getaddrinfo (hoststr, portstr, &aihints, &airesult);
        if (x != 0)
            continue;
        cbret = cbfunc(cbdata, airesult->ai_socktype, airesult->ai_addr);
        freeaddrinfo(airesult);
        if (cbret != 0)
            break;
    }
    Py_DECREF (py_result);
    return 0;
}