#include "libwbclient.h"
+/** @brief The maximum number of pwent structs to get from winbindd
+ *
+ */
+#define MAX_GETPWENT_USERS 500
+
+/** @brief The maximum number of grent structs to get from winbindd
+ *
+ */
+#define MAX_GETGRENT_GROUPS 500
+
/**
*
**/
grp->gr_mem[i] = talloc_strdup(grp, mem_p);
BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
- *mem_q = ',';
- mem_p++;
- mem_p = mem_q;
+ if (mem_q == NULL) {
+ i += 1;
+ break;
+ }
+ mem_p = mem_q + 1;
}
- grp->gr_mem[g->num_gr_mem] = NULL;
+ grp->gr_mem[i] = NULL;
wbc_status = WBC_ERR_SUCCESS;
struct winbindd_request request;
struct winbindd_response response;
- if (!name || !grp) {
- wbc_status = WBC_ERR_INVALID_PARAM;
- BAIL_ON_WBC_ERROR(wbc_status);
- }
-
/* Initialize request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
+ if (!name || !grp) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
/* dst is already null terminated from the memset above */
strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
&response);
BAIL_ON_WBC_ERROR(wbc_status);
- *grp = copy_group_entry(&response.data.gr,
+ *grp = copy_group_entry(&response.data.gr,
(char*)response.extra_data.data);
BAIL_ON_PTR_ERROR(*grp, wbc_status);
done:
if (response.extra_data.data)
free(response.extra_data.data);
-
+
return wbc_status;
}
struct winbindd_request request;
struct winbindd_response response;
- if (!grp) {
- wbc_status = WBC_ERR_INVALID_PARAM;
- BAIL_ON_WBC_ERROR(wbc_status);
- }
-
/* Initialize request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
+ if (!grp) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
request.data.gid = gid;
wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
&response);
BAIL_ON_WBC_ERROR(wbc_status);
- *grp = copy_group_entry(&response.data.gr,
+ *grp = copy_group_entry(&response.data.gr,
(char*)response.extra_data.data);
BAIL_ON_PTR_ERROR(*grp, wbc_status);
return wbc_status;
}
+/** @brief Number of cached passwd structs
+ *
+ */
+static uint32_t pw_cache_size;
+
+/** @brief Position of the pwent context
+ *
+ */
+static uint32_t pw_cache_idx;
+
+/** @brief Winbindd response containing the passwd structs
+ *
+ */
+static struct winbindd_response pw_response;
+
/** @brief Reset the passwd iterator
*
* @return #wbcErr
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (pw_cache_size > 0) {
+ pw_cache_idx = pw_cache_size = 0;
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ }
+ }
+
+ ZERO_STRUCT(pw_response);
+
wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (pw_cache_size > 0) {
+ pw_cache_idx = pw_cache_size = 0;
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ }
+ }
+
wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
/** @brief Return the next struct passwd* entry from the pwent iterator
*
- * @param **pwd Pointer to resulting struct group* from the query.
+ * @param **pwd Pointer to resulting struct passwd* from the query.
*
* @return #wbcErr
**/
wbcErr wbcGetpwent(struct passwd **pwd)
{
- return WBC_ERR_NOT_IMPLEMENTED;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_pw *wb_pw;
+
+ /* If there's a cached result, return that. */
+ if (pw_cache_idx < pw_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ pw_cache_idx = 0;
+
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ ZERO_STRUCT(pw_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETPWENT_USERS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
+ &pw_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ pw_cache_size = pw_response.data.num_entries;
+
+return_result:
+
+ wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
+
+ *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
+
+ BAIL_ON_PTR_ERROR(*pwd, wbc_status);
+
+ pw_cache_idx++;
+
+done:
+ return wbc_status;
}
+/** @brief Number of cached group structs
+ *
+ */
+static uint32_t gr_cache_size;
+
+/** @brief Position of the grent context
+ *
+ */
+static uint32_t gr_cache_idx;
+
+/** @brief Winbindd response containing the group structs
+ *
+ */
+static struct winbindd_response gr_response;
+
/** @brief Reset the group iterator
*
* @return #wbcErr
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (gr_cache_size > 0) {
+ gr_cache_idx = gr_cache_size = 0;
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ }
+ }
+
+ ZERO_STRUCT(gr_response);
+
wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (gr_cache_size > 0) {
+ gr_cache_idx = gr_cache_size = 0;
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ }
+ }
+
wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
return wbc_status;
}
-/** @brief Return the next struct passwd* entry from the pwent iterator
+/** @brief Return the next struct group* entry from the pwent iterator
*
* @param **grp Pointer to resulting struct group* from the query.
*
wbcErr wbcGetgrent(struct group **grp)
{
- return WBC_ERR_NOT_IMPLEMENTED;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_gr *wb_gr;
+ uint32_t mem_ofs;
+
+ /* If there's a cached result, return that. */
+ if (gr_cache_idx < gr_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ gr_cache_idx = 0;
+
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ ZERO_STRUCT(gr_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETGRENT_GROUPS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
+ &gr_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ gr_cache_size = gr_response.data.num_entries;
+
+return_result:
+
+ wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
+
+ mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
+ gr_cache_size * sizeof(struct winbindd_gr);
+
+ *grp = copy_group_entry(&wb_gr[gr_cache_idx],
+ ((char *)gr_response.extra_data.data)+mem_ofs);
+
+ BAIL_ON_PTR_ERROR(*grp, wbc_status);
+
+ gr_cache_idx++;
+
+done:
+ return wbc_status;
+}
+
+/** @brief Return the next struct group* entry from the pwent iterator
+ *
+ * This is similar to #wbcGetgrent, just that the member list is empty
+ *
+ * @param **grp Pointer to resulting struct group* from the query.
+ *
+ * @return #wbcErr
+ **/
+
+wbcErr wbcGetgrlist(struct group **grp)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_gr *wb_gr;
+
+ /* If there's a cached result, return that. */
+ if (gr_cache_idx < gr_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ gr_cache_idx = 0;
+
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ ZERO_STRUCT(gr_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETGRENT_GROUPS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
+ &gr_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ gr_cache_size = gr_response.data.num_entries;
+
+return_result:
+
+ wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
+
+ *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
+
+ BAIL_ON_PTR_ERROR(*grp, wbc_status);
+
+ gr_cache_idx++;
+
+done:
+ return wbc_status;
}
+/** @brief Return the unix group array belonging to the given user
+ *
+ * @param *account The given user name
+ * @param *num_groups Number of elements returned in the groups array
+ * @param **_groups Pointer to resulting gid_t array.
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcGetGroups(const char *account,
+ uint32_t *num_groups,
+ gid_t **_groups)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ uint32_t i;
+ gid_t *groups = NULL;
+
+ /* Initialize request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (!account) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ /* Send request */
+
+ strncpy(request.data.username, account, sizeof(request.data.username)-1);
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
+ &request,
+ &response);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ groups = talloc_array(NULL, gid_t, response.data.num_entries);
+ BAIL_ON_PTR_ERROR(groups, wbc_status);
+
+ for (i = 0; i < response.data.num_entries; i++) {
+ groups[i] = ((gid_t *)response.extra_data.data)[i];
+ }
+
+ *num_groups = response.data.num_entries;
+ *_groups = groups;
+ groups = NULL;
+
+ wbc_status = WBC_ERR_SUCCESS;
+
+ done:
+ if (response.extra_data.data) {
+ free(response.extra_data.data);
+ }
+ if (groups) {
+ talloc_free(groups);
+ }
+
+ return wbc_status;
+}