int sysapi_queue_deque_all(void (*cbfunc)(void *elem, void *magic), void *magic, void *qptr) { struct sysapi_queue_head *qhead = qptr; struct sysapi_queue *elem; elem = qhead->head; for (; elem;) { cbfunc(elem->data, magic); qhead->head = elem->next; free(elem); elem = qhead->head; } }
int sysapi_queue_deque(void (*cbfunc)(void *elem, void *magic), void *magic, void *qptr) { struct sysapi_queue_head *qhead = qptr; struct sysapi_queue *elem; elem = qhead->head; if (!elem) return -1; cbfunc(elem->data, magic); qhead->head = elem->next; free(elem); return 0; }
static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name, const char *service, struct addrinfo *in, int (*cbfunc)(void *, int, struct sockaddr *), void *cbdata) { struct addrinfo *out = NULL; int ret; int count = 3; while (count) { ret = getaddrinfo(name, service, in, &out); if (ret == 0) { break; } if (ret == EAI_AGAIN) { count--; continue; } #ifdef DEBUG_KRB5 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " "getaddrinfo failed: %s (%d)\n", (unsigned int)getpid(), gai_strerror(ret), ret); #endif return KRB5_PLUGIN_NO_HANDLE; } ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr); #ifdef DEBUG_KRB5 if (ret) { fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " "failed to call callback: %s (%d)\n", (unsigned int)getpid(), error_message(ret), ret); } #endif freeaddrinfo(out); return ret; }
krb5_error_code _krb5_override_service_locator( void *arg0, enum locate_service_type svc, const char *realm, int socktype, int family, int (*cbfunc)(void *, int, struct sockaddr *), void *cbdata) { _NOTE(ARGUNUSED(arg0)) smb_domainex_t dxi; int rc = KRB5_PLUGIN_NO_HANDLE; short port; /* * Is this a service we want to override? */ switch (svc) { case locate_service_kdc: case locate_service_master_kdc: port = htons(KRB5_DEFAULT_PORT); break; case locate_service_kadmin: port = htons(DEFAULT_KADM5_PORT); break; case locate_service_kpasswd: port = htons(DEFAULT_KPASSWD_PORT); break; case locate_service_krb524: default: return (rc); } /* * What's my domain? Note: have to get this in a way * that works while join domain is underway. */ if (!smb_domain_getinfo(&dxi)) { smbd_report("_krb5_override_service_locator " "failed getting domain info"); return (KRB5_ERR_HOST_REALM_UNKNOWN); } /* * Is this a realm we want to override? */ if (0 != strcasecmp(realm, dxi.d_primary.di_fqname)) { syslog(LOG_DEBUG, "_krb5_override_service_locator, " "realm=%s, fqdn=%s", realm, dxi.d_primary.di_fqname); return (rc); } /* * Yes, this is our domain. Have a DC? */ if (dxi.d_dci.dc_name[0] == '\0' || dxi.d_dci.dc_addr.a_family == 0) return (KRB5_REALM_CANT_RESOLVE); switch (family) { case AF_UNSPEC: break; /* OK */ case AF_INET: case AF_INET6: if (family == dxi.d_dci.dc_addr.a_family) break; /* OK */ /* else fallthrough */ default: return (KRB5_ERR_NO_SERVICE); } /* * Provide the service address we have. */ switch (dxi.d_dci.dc_addr.a_family) { case AF_INET: { struct sockaddr_in sin; (void) memset(&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_port = port; (void) memcpy(&sin.sin_addr, &dxi.d_dci.dc_addr.a_ipv4, sizeof (sin.sin_addr)); rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin); /* rc from cbfunc is special. */ if (rc) rc = ENOMEM; break; } case AF_INET6: { struct sockaddr_in6 sin6; (void) memset(&sin6, 0, sizeof (sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_port = port; (void) memcpy(&sin6.sin6_addr, &dxi.d_dci.dc_addr.a_ipv6, sizeof (sin6.sin6_addr)); rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin6); /* rc from cbfunc is special. */ if (rc) rc = ENOMEM; break; } default: rc = KRB5_ERR_NO_SERVICE; break; } return (rc); }
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; }