Remove trailing withespace from wbinfo -m which breaks gdm auth.
[ira/wip.git] / source3 / nsswitch / wbinfo.c
index 772332ee59272fe981fb1675c4592765a0ad0cec..c1d41a53fdc785e91c867d38966d50a0df09c1f3 100644 (file)
@@ -8,7 +8,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "winbindd.h"
-#include "debug.h"
+#include "winbind_client.h"
+#include "libwbclient/wbclient.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-extern int winbindd_fd;
+static struct wbcInterfaceDetails *init_interface_details(void)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       static struct wbcInterfaceDetails *details;
 
-static char winbind_separator(void)
+       if (details) {
+               return details;
+       }
+
+       wbc_status = wbcInterfaceDetails(&details);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               d_fprintf(stderr, "could not obtain winbind interface details!\n");
+       }
+
+       return details;
+}
+
+static char winbind_separator_int(bool strict)
 {
-       struct winbindd_response response;
-       static BOOL got_sep;
+       struct wbcInterfaceDetails *details;
+       static bool got_sep;
        static char sep;
 
        if (got_sep)
                return sep;
 
-       ZERO_STRUCT(response);
-
-       /* Send off request */
+       details = init_interface_details();
 
-       if (winbindd_request(WINBINDD_INFO, NULL, &response) !=
-           NSS_STATUS_SUCCESS) {
-               d_printf("could not obtain winbind separator!\n");
+       if (!details) {
+               d_fprintf(stderr, "could not obtain winbind separator!\n");
+               if (strict) {
+                       return 0;
+               }
                /* HACK: (this module should not call lp_ funtions) */
                return *lp_winbind_separator();
        }
 
-       sep = response.data.info.winbind_separator;
-       got_sep = True;
+       sep = details->winbind_separator;
+       got_sep = true;
 
        if (!sep) {
-               d_printf("winbind separator was NULL!\n");
+               d_fprintf(stderr, "winbind separator was NULL!\n");
+               if (strict) {
+                       return 0;
+               }
                /* HACK: (this module should not call lp_ funtions) */
                sep = *lp_winbind_separator();
        }
@@ -62,225 +79,432 @@ static char winbind_separator(void)
        return sep;
 }
 
+static char winbind_separator(void)
+{
+       return winbind_separator_int(false);
+}
+
 static const char *get_winbind_domain(void)
 {
-       struct winbindd_response response;
-       static fstring winbind_domain;
+       static struct wbcInterfaceDetails *details;
 
-       ZERO_STRUCT(response);
+       details = init_interface_details();
 
-       /* Send off request */
+       if (!details) {
+               d_fprintf(stderr, "could not obtain winbind domain name!\n");
 
-       if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
-           NSS_STATUS_SUCCESS) {
-               d_printf("could not obtain winbind domain name!\n");
-               
-               /* HACK: (this module should not call lp_ funtions) */
+               /* HACK: (this module should not call lp_ functions) */
                return lp_workgroup();
        }
 
-       fstrcpy(winbind_domain, response.data.domain_name);
-
-       return winbind_domain;
-
+       return details->netbios_domain;
 }
 
 /* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the
    form DOMAIN/user into a domain and a user */
 
-static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain, 
+static bool parse_wbinfo_domain_user(const char *domuser, fstring domain,
                                     fstring user)
 {
 
        char *p = strchr(domuser,winbind_separator());
 
        if (!p) {
+               /* Maybe it was a UPN? */
+               if ((p = strchr(domuser, '@')) != NULL) {
+                       fstrcpy(domain, "");
+                       fstrcpy(user, domuser);
+                       return true;
+               }
+
                fstrcpy(user, domuser);
                fstrcpy(domain, get_winbind_domain());
-               return True;
+               return true;
        }
-        
+
        fstrcpy(user, p+1);
        fstrcpy(domain, domuser);
        domain[PTR_DIFF(p, domuser)] = 0;
        strupper_m(domain);
 
-       return True;
+       return true;
 }
 
-/* List groups a user is a member of */
+/* pull pwent info for a given user */
 
-static BOOL wbinfo_get_usergroups(char *user)
+static bool wbinfo_get_userinfo(char *user)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-       NSS_STATUS result;
-       int i;
-       
-       ZERO_STRUCT(response);
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct passwd *pwd = NULL;
 
-       /* Send request */
+       wbc_status = wbcGetpwnam(user, &pwd);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       fstrcpy(request.data.username, user);
+       d_printf("%s:%s:%d:%d:%s:%s:%s\n",
+                pwd->pw_name,
+                pwd->pw_passwd,
+                pwd->pw_uid,
+                pwd->pw_gid,
+                pwd->pw_gecos,
+                pwd->pw_dir,
+                pwd->pw_shell);
 
-       result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
+       return true;
+}
 
-       if (result != NSS_STATUS_SUCCESS)
-               return False;
+/* pull pwent info for a given uid */
+static bool wbinfo_get_uidinfo(int uid)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct passwd *pwd = NULL;
 
-       for (i = 0; i < response.data.num_entries; i++)
-               d_printf("%d\n", (int)((gid_t *)response.extra_data)[i]);
+       wbc_status = wbcGetpwuid(uid, &pwd);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       SAFE_FREE(response.extra_data);
+       d_printf("%s:%s:%d:%d:%s:%s:%s\n",
+                pwd->pw_name,
+                pwd->pw_passwd,
+                pwd->pw_uid,
+                pwd->pw_gid,
+                pwd->pw_gecos,
+                pwd->pw_dir,
+                pwd->pw_shell);
 
-       return True;
+       return true;
 }
 
-
-/* List group SIDs a user SID is a member of */
-static BOOL wbinfo_get_usersids(char *user_sid)
+/* pull grent for a given group */
+static bool wbinfo_get_groupinfo(const char *group)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-       NSS_STATUS result;
-       int i;
-       const char *s;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct group *grp;
 
-       ZERO_STRUCT(response);
+       wbc_status = wbcGetgrnam(group, &grp);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       /* Send request */
-       fstrcpy(request.data.sid, user_sid);
+       d_printf("%s:%s:%d\n",
+                grp->gr_name,
+                grp->gr_passwd,
+                grp->gr_gid);
 
-       result = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response);
+       wbcFreeMemory(grp);
 
-       if (result != NSS_STATUS_SUCCESS)
-               return False;
+       return true;
+}
+
+/* List groups a user is a member of */
+
+static bool wbinfo_get_usergroups(const char *user)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uint32_t num_groups;
+       uint32_t i;
+       gid_t *groups = NULL;
+
+       /* Send request */
 
-       s = response.extra_data;
-       for (i = 0; i < response.data.num_entries; i++) {
-               d_printf("%s\n", s);
-               s += strlen(s) + 1;
+       wbc_status = wbcGetGroups(user, &num_groups, &groups);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
        }
 
-       SAFE_FREE(response.extra_data);
+       for (i = 0; i < num_groups; i++) {
+               d_printf("%d\n", (int)groups[i]);
+       }
+
+       wbcFreeMemory(groups);
 
-       return True;
+       return true;
 }
 
-/* Convert NetBIOS name to IP */
 
-static BOOL wbinfo_wins_byname(char *name)
+/* List group SIDs a user SID is a member of */
+static bool wbinfo_get_usersids(const char *user_sid_str)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uint32_t num_sids;
+       uint32_t i;
+       struct wbcDomainSid user_sid, *sids = NULL;
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       /* Send request */
+
+       wbc_status = wbcStringToSid(user_sid_str, &user_sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       wbc_status = wbcLookupUserSids(&user_sid, false, &num_sids, &sids);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       for (i = 0; i < num_sids; i++) {
+               char *str = NULL;
+               wbc_status = wbcSidToString(&sids[i], &str);
+               if (!WBC_ERROR_IS_OK(wbc_status)) {
+                       wbcFreeMemory(sids);
+                       return false;
+               }
+               d_printf("%s\n", str);
+               wbcFreeMemory(str);
+       }
+
+       wbcFreeMemory(sids);
+
+       return true;
+}
+
+static bool wbinfo_get_userdomgroups(const char *user_sid_str)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uint32_t num_sids;
+       uint32_t i;
+       struct wbcDomainSid user_sid, *sids = NULL;
 
        /* Send request */
 
-       fstrcpy(request.data.winsreq, name);
+       wbc_status = wbcStringToSid(user_sid_str, &user_sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       if (winbindd_request(WINBINDD_WINS_BYNAME, &request, &response) !=
-           NSS_STATUS_SUCCESS) {
-               return False;
+       wbc_status = wbcLookupUserSids(&user_sid, true, &num_sids, &sids);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
        }
 
-       /* Display response */
+       for (i = 0; i < num_sids; i++) {
+               char *str = NULL;
+               wbc_status = wbcSidToString(&sids[i], &str);
+               if (!WBC_ERROR_IS_OK(wbc_status)) {
+                       wbcFreeMemory(sids);
+                       return false;
+               }
+               d_printf("%s\n", str);
+               wbcFreeMemory(str);
+       }
 
-       printf("%s\n", response.data.winsresp);
+       wbcFreeMemory(sids);
 
-       return True;
+       return true;
 }
 
-/* Convert IP to NetBIOS name */
+/* Convert NetBIOS name to IP */
 
-static BOOL wbinfo_wins_byip(char *ip)
+static bool wbinfo_wins_byname(const char *name)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       char *ip = NULL;
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbc_status = wbcResolveWinsByName(name, &ip);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       /* Send request */
+       /* Display response */
 
-       fstrcpy(request.data.winsreq, ip);
+       d_printf("%s\n", ip);
 
-       if (winbindd_request(WINBINDD_WINS_BYIP, &request, &response) !=
-           NSS_STATUS_SUCCESS) {
-               return False;
+       wbcFreeMemory(ip);
+
+       return true;
+}
+
+/* Convert IP to NetBIOS name */
+
+static bool wbinfo_wins_byip(const char *ip)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       char *name = NULL;
+
+       wbc_status = wbcResolveWinsByIP(ip, &name);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
        }
 
        /* Display response */
 
-       printf("%s\n", response.data.winsresp);
+       d_printf("%s\n", name);
+
+       wbcFreeMemory(name);
 
-       return True;
+       return true;
 }
 
-/* List trusted domains */
+/* List all/trusted domains */
 
-static BOOL wbinfo_list_domains(void)
+static bool wbinfo_list_domains(bool list_all_domains, bool verbose)
 {
-       struct winbindd_response response;
-       fstring name;
+       struct wbcDomainInfo *domain_list = NULL;
+       size_t num_domains;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       bool print_all = !list_all_domains && verbose;
+       int i;
 
-       ZERO_STRUCT(response);
+       wbc_status = wbcListTrusts(&domain_list, &num_domains);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       /* Send request */
+       if (print_all) {
+               d_printf("%-16s%-24s%-12s%-12s%-5s%-5s\n", 
+                        "Domain Name", "DNS Domain", "Trust Type", 
+                        "Transitive", "In", "Out");
+       }
 
-       if (winbindd_request(WINBINDD_LIST_TRUSTDOM, NULL, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       for (i=0; i<num_domains; i++) {
+               if (print_all) {
+                       d_printf("%-16s", domain_list[i].short_name);
+               } else {
+                       d_printf("%s", domain_list[i].short_name);
+                       d_printf("\n");
+                       continue;
+               }
 
-       /* Display response */
+               d_printf("%-24s", domain_list[i].dns_name);
 
-       if (response.extra_data) {
-               const char *extra_data = (char *)response.extra_data;
+               switch(domain_list[i].trust_type) {
+               case WBC_DOMINFO_TRUSTTYPE_NONE:
+                       d_printf("None        ");
+                       break;
+               case WBC_DOMINFO_TRUSTTYPE_FOREST:              
+                       d_printf("Forest      ");
+                       break;
+               case WBC_DOMINFO_TRUSTTYPE_EXTERNAL:            
+                       d_printf("External    ");
+                       break;
+               case WBC_DOMINFO_TRUSTTYPE_IN_FOREST:
+                       d_printf("In-Forest   ");
+                       break;
+               }
 
-               while(next_token(&extra_data, name, ",", sizeof(fstring)))
-                       d_printf("%s\n", name);
+               if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_TRANSITIVE) {
+                       d_printf("Yes         ");
+               } else {
+                       d_printf("No          ");
+               }
 
-               SAFE_FREE(response.extra_data);
+               if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_INCOMING) {
+                       d_printf("Yes  ");
+               } else {
+                       d_printf("No   ");
+               }
+
+               if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_OUTGOING) {
+                       d_printf("Yes  ");
+               } else {
+                       d_printf("No   ");
+               }
+
+               d_printf("\n");
        }
 
-       return True;
+       return true;
 }
 
+/* List own domain */
 
-/* show sequence numbers */
-static BOOL wbinfo_show_sequence(const char *domain)
+static bool wbinfo_list_own_domain(void)
 {
-       struct winbindd_request  request;
-       struct winbindd_response response;
+       d_printf("%s\n", get_winbind_domain());
 
-       ZERO_STRUCT(response);
-       ZERO_STRUCT(request);
+       return true;
+}
 
-       if ( domain )
-               fstrcpy( request.domain_name, domain );
+/* show sequence numbers */
+static bool wbinfo_show_sequence(const char *domain)
+{
+       d_printf("This command has been deprecated.  Please use the --online-status option instead.\n");
+       return false;
+}
 
-       /* Send request */
+/* show sequence numbers */
+static bool wbinfo_show_onlinestatus(const char *domain)
+{
+       struct wbcDomainInfo *domain_list = NULL;
+       size_t num_domains;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       int i;
 
-       if (winbindd_request(WINBINDD_SHOW_SEQUENCE, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcListTrusts(&domain_list, &num_domains);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       /* Display response */
+       for (i=0; i<num_domains; i++) {
+               bool is_offline;
+
+               if (domain) {
+                       if (!strequal(domain_list[i].short_name, domain)) {
+                               continue;
+                       }
+               }
 
-       if (response.extra_data) {
-               char *extra_data = (char *)response.extra_data;
-               d_printf("%s", extra_data);
-               SAFE_FREE(response.extra_data);
+               is_offline = (domain_list[i].domain_flags & WBC_DOMINFO_DOMAIN_OFFLINE);
+               
+               d_printf("%s : %s\n", 
+                        domain_list[i].short_name,
+                        is_offline ? "offline" : "online" );
        }
 
-       return True;
+       return true;
 }
 
+
 /* Show domain info */
 
-static BOOL wbinfo_domain_info(const char *domain_name)
+static bool wbinfo_domain_info(const char *domain)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainInfo *dinfo = NULL;
+       char *sid_str = NULL;
+
+       if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) {
+               domain = get_winbind_domain();
+       }
+
+       /* Send request */
+
+       wbc_status = wbcDomainInfo(domain, &dinfo);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       wbc_status = wbcSidToString(&dinfo->sid, &sid_str);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               wbcFreeMemory(dinfo);
+               return false;
+       }
+
+       /* Display response */
+
+       d_printf("Name              : %s\n", dinfo->short_name);
+       d_printf("Alt_Name          : %s\n", dinfo->dns_name);
+
+       d_printf("SID               : %s\n", sid_str);
+
+       d_printf("Active Directory  : %s\n",
+                (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No");
+       d_printf("Native            : %s\n",
+                (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ? "Yes" : "No");
+
+       d_printf("Primary           : %s\n",
+                (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ? "Yes" : "No");
+
+       wbcFreeMemory(sid_str);
+       wbcFreeMemory(dinfo);
+
+       return true;
+}
+
+/* Get a foreign DC's name */
+static bool wbinfo_getdcname(const char *domain_name)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -292,576 +516,726 @@ static BOOL wbinfo_domain_info(const char *domain_name)
 
        /* Send request */
 
-       if (winbindd_request(WINBINDD_DOMAIN_INFO, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) !=
+           NSS_STATUS_SUCCESS) {
+               d_fprintf(stderr, "Could not get dc name for %s\n", domain_name);
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("Name              : %s\n", response.data.domain_info.name);
-       d_printf("Alt_Name          : %s\n", response.data.domain_info.alt_name);
+       d_printf("%s\n", response.data.dc_name);
 
-       d_printf("SID               : %s\n", response.data.domain_info.sid);
+       return true;
+}
 
-       d_printf("Active Directory  : %s\n",
-                response.data.domain_info.active_directory ? "Yes" : "No");
-       d_printf("Native            : %s\n",
-                response.data.domain_info.native_mode ? "Yes" : "No");
+/* Find a DC */
+static bool wbinfo_dsgetdcname(const char *domain_name, uint32_t flags)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
 
-       d_printf("Primary           : %s\n",
-                response.data.domain_info.primary ? "Yes" : "No");
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       fstrcpy(request.domain_name, domain_name);
+       request.flags = flags;
+
+       request.flags |= DS_DIRECTORY_SERVICE_REQUIRED;
+
+       /* Send request */
+
+       if (winbindd_request_response(WINBINDD_DSGETDCNAME, &request, &response) !=
+           NSS_STATUS_SUCCESS) {
+               d_fprintf(stderr, "Could not find dc for %s\n", domain_name);
+               return false;
+       }
 
-       d_printf("Sequence          : %d\n", response.data.domain_info.sequence_number);
+       /* Display response */
+
+       d_printf("%s\n", response.data.dc_name);
 
-       return True;
+       return true;
 }
 
 /* Check trust account password */
 
-static BOOL wbinfo_check_secret(void)
+static bool wbinfo_check_secret(void)
 {
-        struct winbindd_response response;
-        NSS_STATUS result;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcAuthErrorInfo *error = NULL;
 
-        ZERO_STRUCT(response);
+       wbc_status = wbcCheckTrustCredentials(NULL, &error);
 
-        result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response);
-               
-       d_printf("checking the trust secret via RPC calls %s\n", 
-                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+       d_printf("checking the trust secret via RPC calls %s\n",
+                WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
 
-       if (result != NSS_STATUS_SUCCESS)       
-               d_printf("error code was %s (0x%x)\n", 
-                        response.data.auth.nt_status_string, 
-                        response.data.auth.nt_status);
-       
-       return result == NSS_STATUS_SUCCESS;    
+       if (wbc_status == WBC_ERR_AUTH_ERROR) {
+               d_fprintf(stderr, "error code was %s (0x%x)\n",
+                         error->nt_string, error->nt_status);
+               wbcFreeMemory(error);
+       }
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       return true;
 }
 
 /* Convert uid to sid */
 
-static BOOL wbinfo_uid_to_sid(uid_t uid)
+static bool wbinfo_uid_to_sid(uid_t uid)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       char *sid_str = NULL;
 
        /* Send request */
 
-       request.data.uid = uid;
+       wbc_status = wbcUidToSid(uid, &sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       if (winbindd_request(WINBINDD_UID_TO_SID, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcSidToString(&sid, &sid_str);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("%s\n", response.data.sid.sid);
+       d_printf("%s\n", sid_str);
 
-       return True;
+       wbcFreeMemory(sid_str);
+
+       return true;
 }
 
 /* Convert gid to sid */
 
-static BOOL wbinfo_gid_to_sid(gid_t gid)
+static bool wbinfo_gid_to_sid(gid_t gid)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       char *sid_str = NULL;
 
        /* Send request */
 
-       request.data.gid = gid;
+       wbc_status = wbcGidToSid(gid, &sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       if (winbindd_request(WINBINDD_GID_TO_SID, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcSidToString(&sid, &sid_str);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("%s\n", response.data.sid.sid);
+       d_printf("%s\n", sid_str);
 
-       return True;
+       wbcFreeMemory(sid_str);
+
+       return true;
 }
 
 /* Convert sid to uid */
 
-static BOOL wbinfo_sid_to_uid(char *sid)
+static bool wbinfo_sid_to_uid(const char *sid_str)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       uid_t uid;
 
        /* Send request */
 
-       fstrcpy(request.data.sid, sid);
+       wbc_status = wbcStringToSid(sid_str, &sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       if (winbindd_request(WINBINDD_SID_TO_UID, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcSidToUid(&sid, &uid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("%d\n", (int)response.data.uid);
+       d_printf("%d\n", (int)uid);
 
-       return True;
+       return true;
 }
 
-static BOOL wbinfo_sid_to_gid(char *sid)
+static bool wbinfo_sid_to_gid(const char *sid_str)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       gid_t gid;
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       /* Send request */
+
+       wbc_status = wbcStringToSid(sid_str, &sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       wbc_status = wbcSidToGid(&sid, &gid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       /* Display response */
+
+       d_printf("%d\n", (int)gid);
+
+       return true;
+}
+
+static bool wbinfo_allocate_uid(void)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uid_t uid;
 
        /* Send request */
 
-       fstrcpy(request.data.sid, sid);
+       wbc_status = wbcAllocateUid(&uid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
+
+       /* Display response */
+
+       d_printf("New uid: %d\n", uid);
+
+       return true;
+}
+
+static bool wbinfo_allocate_gid(void)
+{
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       gid_t gid;
+
+       /* Send request */
 
-       if (winbindd_request(WINBINDD_SID_TO_GID, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcAllocateGid(&gid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("%d\n", (int)response.data.gid);
+       d_printf("New gid: %d\n", gid);
 
-       return True;
+       return true;
 }
 
 /* Convert sid to string */
 
-static BOOL wbinfo_lookupsid(char *sid)
+static bool wbinfo_lookupsid(const char *sid_str)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       char *domain;
+       char *name;
+       enum wbcSidType type;
 
        /* Send off request */
 
-       fstrcpy(request.data.sid, sid);
+       wbc_status = wbcStringToSid(sid_str, &sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       wbc_status = wbcLookupSid(&sid, &domain, &name, &type);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-       d_printf("%s%c%s %d\n", response.data.name.dom_name, 
-                winbind_separator(), response.data.name.name, 
-                response.data.name.type);
+       d_printf("%s%c%s %d\n",
+                domain, winbind_separator(), name, type);
 
-       return True;
+       return true;
 }
 
-/* Convert string to sid */
+/* Lookup a list of RIDs */
 
-static BOOL wbinfo_lookupname(char *name)
+static bool wbinfo_lookuprids(const char *domain, const char *arg)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainInfo *dinfo = NULL;
+       char *domain_name = NULL;
+       const char **names = NULL;
+       enum wbcSidType *types = NULL;
+       size_t i;
+       int num_rids;
+       uint32 *rids = NULL;
+       const char *p;
+       char *ridstr;
+       TALLOC_CTX *mem_ctx = NULL;
+       bool ret = false;
+
+       if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) {
+               domain = get_winbind_domain();
+       }
 
-       /* Send off request */
+       /* Send request */
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       wbc_status = wbcDomainInfo(domain, &dinfo);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               d_printf("wbcDomainInfo(%s) failed: %s\n", domain,
+                        wbcErrorString(wbc_status));
+               goto done;
+       }
 
-       parse_wbinfo_domain_user(name, request.data.name.dom_name, 
-                                request.data.name.name);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               d_printf("talloc_new failed\n");
+               goto done;
+       }
 
-       if (winbindd_request(WINBINDD_LOOKUPNAME, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
+       num_rids = 0;
+       rids = NULL;
+       p = arg;
 
-       /* Display response */
+       while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) {
+               uint32 rid = strtoul(ridstr, NULL, 10);
+               ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids);
+       }
 
-       d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type);
+       if (rids == NULL) {
+               d_printf("no rids\n");
+               goto done;
+       }
 
-       return True;
+       wbc_status = wbcLookupRids(&dinfo->sid, num_rids, rids,
+                                  (const char **)&domain_name, &names, &types);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               d_printf("winbind_lookup_rids failed: %s\n",
+                        wbcErrorString(wbc_status));
+               goto done;
+       }
+
+       d_printf("Domain: %s\n", domain_name);
+
+       for (i=0; i<num_rids; i++) {
+               d_printf("%8d: %s (%s)\n", rids[i], names[i],
+                        sid_type_lookup(types[i]));
+       }
+
+       ret = true;
+done:
+       if (dinfo) {
+               wbcFreeMemory(dinfo);
+       }
+       if (domain_name) {
+               wbcFreeMemory(domain_name);
+       }
+       if (names) {
+               wbcFreeMemory(names);
+       }
+       if (types) {
+               wbcFreeMemory(types);
+       }
+       TALLOC_FREE(mem_ctx);
+       return ret;
 }
 
-/* Authenticate a user with a plaintext password */
+/* Convert string to sid */
 
-static BOOL wbinfo_auth(char *username)
+static bool wbinfo_lookupname(const char *full_name)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
-        char *p;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcDomainSid sid;
+       char *sid_str;
+       enum wbcSidType type;
+       fstring domain_name;
+       fstring account_name;
 
        /* Send off request */
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       parse_wbinfo_domain_user(full_name, domain_name,
+                                account_name);
 
-        p = strchr(username, '%');
-
-        if (p) {
-                *p = 0;
-                fstrcpy(request.data.auth.user, username);
-                fstrcpy(request.data.auth.pass, p + 1);
-                *p = '%';
-        } else
-                fstrcpy(request.data.auth.user, username);
+       wbc_status = wbcLookupName(domain_name, account_name,
+                                  &sid, &type);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response);
+       wbc_status = wbcSidToString(&sid, &sid_str);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
        /* Display response */
 
-        d_printf("plaintext password authentication %s\n", 
-               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+       d_printf("%s %s (%d)\n", sid_str, sid_type_lookup(type), type);
 
-       if (response.data.auth.nt_status)
-               d_printf("error code was %s (0x%x)\nerror messsage was: %s\n", 
-                        response.data.auth.nt_status_string, 
-                        response.data.auth.nt_status,
-                        response.data.auth.error_string);
+       wbcFreeMemory(sid_str);
 
-        return result == NSS_STATUS_SUCCESS;
+       return true;
 }
 
-/* Authenticate a user with a challenge/response */
+/* Authenticate a user with a plaintext password */
 
-static BOOL wbinfo_auth_crap(char *username)
+static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32 flags)
 {
        struct winbindd_request request;
        struct winbindd_response response;
-        NSS_STATUS result;
-        fstring name_user;
-        fstring name_domain;
-        fstring pass;
-        char *p;
+       NSS_STATUS result;
+       char *p;
 
        /* Send off request */
 
        ZERO_STRUCT(request);
        ZERO_STRUCT(response);
 
-        p = strchr(username, '%');
-
-        if (p) {
-                *p = 0;
-                fstrcpy(pass, p + 1);
-       }
-               
-       parse_wbinfo_domain_user(username, name_domain, name_user);
+       p = strchr(username, '%');
 
-       if (push_utf8_fstring(request.data.auth_crap.user, name_user) == -1) {
-               d_printf("unable to create utf8 string for '%s'\n",
-                        name_user);
-               return False;
-       }
+       if (p) {
+               *p = 0;
+               fstrcpy(request.data.auth.user, username);
+               fstrcpy(request.data.auth.pass, p + 1);
+               *p = '%';
+       } else
+               fstrcpy(request.data.auth.user, username);
 
-       if (push_utf8_fstring(request.data.auth_crap.domain, 
-                             name_domain) == -1) {
-               d_printf("unable to create utf8 string for '%s'\n",
-                        name_domain);
-               return False;
-       }
+       request.flags = flags;
 
-       generate_random_buffer(request.data.auth_crap.chal, 8, False);
-        
-        SMBencrypt(pass, request.data.auth_crap.chal, 
-                   (uchar *)request.data.auth_crap.lm_resp);
-        SMBNTencrypt(pass, request.data.auth_crap.chal,
-                     (uchar *)request.data.auth_crap.nt_resp);
+       fstrcpy(request.data.auth.krb5_cc_type, cctype);
 
-        request.data.auth_crap.lm_resp_len = 24;
-        request.data.auth_crap.nt_resp_len = 24;
+       request.data.auth.uid = geteuid();
 
-       result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+       result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
 
        /* Display response */
 
-        d_printf("challenge/response password authentication %s\n", 
-               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+       d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", 
+               username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
 
        if (response.data.auth.nt_status)
-               d_printf("error code was %s (0x%x)\nerror messsage was: %s\n", 
+               d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
                         response.data.auth.nt_status_string, 
                         response.data.auth.nt_status,
                         response.data.auth.error_string);
 
-        return result == NSS_STATUS_SUCCESS;
+       if (result == NSS_STATUS_SUCCESS) {
+
+               if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
+                       if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) {
+                               d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n");
+                       }
+               }
+
+               if (response.data.auth.krb5ccname[0] != '\0') {
+                       d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
+               } else {
+                       d_printf("no credentials cached\n");
+               }
+       }
+
+       return result == NSS_STATUS_SUCCESS;
 }
 
-/******************************************************************
- create a winbindd user
-******************************************************************/
+/* Authenticate a user with a plaintext password */
 
-static BOOL wbinfo_create_user(char *username)
+static bool wbinfo_auth(char *username)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       char *s = NULL;
+       char *p = NULL;
+       const char *password = NULL;
+       char *name = NULL;
+
+       if ((s = SMB_STRDUP(username)) == NULL) {
+               return false;
+       }
 
-       /* Send off request */
+       if ((p = strchr(s, '%')) != NULL) {
+               *p = 0;
+               p++;
+               password = p;
+       } else {
+               char *prompt;
+               asprintf(&prompt, "Enter %s's password:", username);
+               if (!prompt) {
+                       return false;
+               }
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+               password = getpass(prompt);
+               SAFE_FREE(prompt);
+       }
 
-       request.flags = WBFLAG_ALLOCATE_RID;
-       fstrcpy(request.data.acct_mgt.username, username);
+       name = s;
 
-       result = winbindd_request(WINBINDD_CREATE_USER, &request, &response);
-       
-       if ( result == NSS_STATUS_SUCCESS )
-               d_printf("New RID is %d\n", response.data.rid);
-       
-        return result == NSS_STATUS_SUCCESS;
+       wbc_status = wbcAuthenticateUser(name, password);
+
+       d_printf("plaintext password authentication %s\n",
+                WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+#if 0
+       if (response.data.auth.nt_status)
+               d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
+                        response.data.auth.nt_status_string,
+                        response.data.auth.nt_status,
+                        response.data.auth.error_string);
+#endif
+
+       SAFE_FREE(s);
+
+       return WBC_ERROR_IS_OK(wbc_status);
 }
 
-/******************************************************************
- remove a winbindd user
-******************************************************************/
+/* Authenticate a user with a challenge/response */
 
-static BOOL wbinfo_delete_user(char *username)
+static bool wbinfo_auth_crap(char *username)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct wbcAuthUserParams params;
+       struct wbcAuthUserInfo *info = NULL;
+       struct wbcAuthErrorInfo *err = NULL;
+       DATA_BLOB lm = data_blob_null;
+       DATA_BLOB nt = data_blob_null;
+       fstring name_user;
+       fstring name_domain;
+       fstring pass;
+       char *p;
 
-       /* Send off request */
+       p = strchr(username, '%');
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       if (p) {
+               *p = 0;
+               fstrcpy(pass, p + 1);
+       } else {
+               char *prompt;
+               asprintf(&prompt, "Enter %s's password:", username);
+               if (!prompt) {
+                       return false;
+               }
 
-       fstrcpy(request.data.acct_mgt.username, username);
+               fstrcpy(pass, getpass(prompt));
+               SAFE_FREE(prompt);
 
-       result = winbindd_request(WINBINDD_DELETE_USER, &request, &response);
-       
-        return result == NSS_STATUS_SUCCESS;
-}
+       }
+               
+       parse_wbinfo_domain_user(username, name_domain, name_user);
 
-/******************************************************************
- create a winbindd group
-******************************************************************/
+       params.account_name     = name_user;
+       params.domain_name      = name_domain;
+       params.workstation_name = NULL;
 
-static BOOL wbinfo_create_group(char *groupname)
-{
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
+       params.flags            = 0;
+       params.parameter_control= WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
+                                 WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
 
-       /* Send off request */
+       params.level            = WBC_AUTH_USER_LEVEL_RESPONSE;
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       generate_random_buffer(params.password.response.challenge, 8);
 
-       fstrcpy(request.data.acct_mgt.groupname, groupname);
+       if (lp_client_ntlmv2_auth()) {
+               DATA_BLOB server_chal;
+               DATA_BLOB names_blob;
 
-       result = winbindd_request(WINBINDD_CREATE_GROUP, &request, &response);
-       
-        return result == NSS_STATUS_SUCCESS;
-}
+               server_chal = data_blob(params.password.response.challenge, 8);
 
-/******************************************************************
- remove a winbindd group
-******************************************************************/
+               /* Pretend this is a login to 'us', for blob purposes */
+               names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup());
 
-static BOOL wbinfo_delete_group(char *groupname)
-{
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
+               if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal,
+                                     &names_blob,
+                                     &lm, &nt, NULL)) {
+                       data_blob_free(&names_blob);
+                       data_blob_free(&server_chal);
+                       return false;
+               }
+               data_blob_free(&names_blob);
+               data_blob_free(&server_chal);
 
-       /* Send off request */
+       } else {
+               if (lp_client_lanman_auth()) {
+                       bool ok;
+                       lm = data_blob(NULL, 24);
+                       ok = SMBencrypt(pass, params.password.response.challenge,
+                                       lm.data);
+                       if (!ok) {
+                               data_blob_free(&lm);
+                       }
+               }
+               nt = data_blob(NULL, 24);
+               SMBNTencrypt(pass, params.password.response.challenge,
+                            nt.data);
+       }
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       params.password.response.nt_length      = nt.length;
+       params.password.response.nt_data        = nt.data;
+       params.password.response.lm_length      = lm.length;
+       params.password.response.lm_data        = lm.data;
 
-       fstrcpy(request.data.acct_mgt.groupname, groupname);
+       wbc_status = wbcAuthenticateUserEx(&params, &info, &err);
 
-       result = winbindd_request(WINBINDD_DELETE_GROUP, &request, &response);
-       
-        return result == NSS_STATUS_SUCCESS;
-}
+       /* Display response */
 
-/******************************************************************
- parse a string in the form user:group
-******************************************************************/
+       d_printf("challenge/response password authentication %s\n",
+                WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+       if (wbc_status == WBC_ERR_AUTH_ERROR) {
+               d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
+                        err->nt_string,
+                        err->nt_status,
+                        err->display_string);
+               wbcFreeMemory(err);
+       } else if (WBC_ERROR_IS_OK(wbc_status)) {
+               wbcFreeMemory(info);
+       }
 
-static BOOL parse_user_group( const char *string, fstring user, fstring group )
-{
-       char *p;
-       
-       if ( !string )
-               return False;
-       
-       if ( !(p = strchr( string, ':' )) )
-               return False;
-               
-       *p = '\0';
-       p++;
-       
-       fstrcpy( user, string );
-       fstrcpy( group, p );
-       
-       return True;
+       data_blob_free(&nt);
+       data_blob_free(&lm);
+
+       return WBC_ERROR_IS_OK(wbc_status);
 }
 
-/******************************************************************
- add a user to a winbindd group
-******************************************************************/
+/* Authenticate a user with a plaintext password and set a token */
 
-static BOOL wbinfo_add_user_to_group(char *string)
+static bool wbinfo_klog(char *username)
 {
        struct winbindd_request request;
        struct winbindd_response response;
-        NSS_STATUS result;
+       NSS_STATUS result;
+       char *p;
 
        /* Send off request */
 
        ZERO_STRUCT(request);
        ZERO_STRUCT(response);
 
-       if ( !parse_user_group( string, request.data.acct_mgt.username,
-               request.data.acct_mgt.groupname))
-       {
-               d_printf("Can't parse user:group from %s\n", string);
-               return False;
+       p = strchr(username, '%');
+
+       if (p) {
+               *p = 0;
+               fstrcpy(request.data.auth.user, username);
+               fstrcpy(request.data.auth.pass, p + 1);
+               *p = '%';
+       } else {
+               fstrcpy(request.data.auth.user, username);
+               fstrcpy(request.data.auth.pass, getpass("Password: "));
        }
 
-       result = winbindd_request(WINBINDD_ADD_USER_TO_GROUP, &request, &response);
-       
-        return result == NSS_STATUS_SUCCESS;
-}
+       request.flags |= WBFLAG_PAM_AFS_TOKEN;
 
-/******************************************************************
- remove a user from a winbindd group
-******************************************************************/
+       result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
 
-static BOOL wbinfo_remove_user_from_group(char *string)
-{
-       struct winbindd_request request;
-       struct winbindd_response response;
-        NSS_STATUS result;
+       /* Display response */
 
-       /* Send off request */
+       d_printf("plaintext password authentication %s\n",
+                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       if (response.data.auth.nt_status)
+               d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
+                        response.data.auth.nt_status_string,
+                        response.data.auth.nt_status,
+                        response.data.auth.error_string);
+
+       if (result != NSS_STATUS_SUCCESS)
+               return false;
 
-       if ( !parse_user_group( string, request.data.acct_mgt.username,
-               request.data.acct_mgt.groupname))
-       {
-               d_printf("Can't parse user:group from %s\n", string);
-               return False;
+       if (response.extra_data.data == NULL) {
+               d_fprintf(stderr, "Did not get token data\n");
+               return false;
        }
 
-       result = winbindd_request(WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
-       
-        return result == NSS_STATUS_SUCCESS;
+       if (!afs_settoken_str((char *)response.extra_data.data)) {
+               d_fprintf(stderr, "Could not set token\n");
+               return false;
+       }
+
+       d_printf("Successfully created AFS token\n");
+       return true;
 }
 
 /* Print domain users */
 
-static BOOL print_domain_users(const char *domain)
+static bool print_domain_users(const char *domain)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-       const char *extra_data;
-       fstring name;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uint32_t i;
+       uint32_t num_users = 0;
+       const char **users = NULL;
 
        /* Send request to winbind daemon */
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
-       
-       if (domain) {
-               /* '.' is the special sign for our own domwin */
-               if ( strequal(domain, ".") )
-                       fstrcpy( request.domain_name, lp_workgroup() );
-               else
-                       fstrcpy( request.domain_name, domain );
+       /* '.' is the special sign for our own domain */
+       if (domain && strcmp(domain, ".") == 0) {
+               domain = get_winbind_domain();
        }
 
-       if (winbindd_request(WINBINDD_LIST_USERS, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
-
-       /* Look through extra data */
-
-       if (!response.extra_data)
-               return False;
+       wbc_status = wbcListUsers(domain, &num_users, &users);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       extra_data = (const char *)response.extra_data;
+       for (i=0; i < num_users; i++) {
+               d_printf("%s\n", users[i]);
+       }
 
-       while(next_token(&extra_data, name, ",", sizeof(fstring)))
-               d_printf("%s\n", name);
-       
-       SAFE_FREE(response.extra_data);
+       wbcFreeMemory(users);
 
-       return True;
+       return true;
 }
 
 /* Print domain groups */
 
-static BOOL print_domain_groups(const char *domain)
+static bool print_domain_groups(const char *domain)
 {
-       struct winbindd_request  request;
-       struct winbindd_response response;
-       const char *extra_data;
-       fstring name;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       uint32_t i;
+       uint32_t num_groups = 0;
+       const char **groups = NULL;
 
-       ZERO_STRUCT(request);
-       ZERO_STRUCT(response);
+       /* Send request to winbind daemon */
 
-       if (domain) {
-               if ( strequal(domain, ".") )
-                       fstrcpy( request.domain_name, lp_workgroup() );
-               else
-                       fstrcpy( request.domain_name, domain );
+       /* '.' is the special sign for our own domain */
+       if (domain && strcmp(domain, ".") == 0) {
+               domain = get_winbind_domain();
        }
 
-       if (winbindd_request(WINBINDD_LIST_GROUPS, &request, &response) !=
-           NSS_STATUS_SUCCESS)
-               return False;
-
-       /* Look through extra data */
-
-       if (!response.extra_data)
-               return False;
+       wbc_status = wbcListGroups(domain, &num_groups, &groups);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return false;
+       }
 
-       extra_data = (const char *)response.extra_data;
+       for (i=0; i < num_groups; i++) {
+               d_printf("%s\n", groups[i]);
+       }
 
-       while(next_token(&extra_data, name, ",", sizeof(fstring)))
-               d_printf("%s\n", name);
+       wbcFreeMemory(groups);
 
-       SAFE_FREE(response.extra_data);
-       
-       return True;
+       return true;
 }
 
 /* Set the authorised user for winbindd access in secrets.tdb */
 
-static BOOL wbinfo_set_auth_user(char *username)
+static bool wbinfo_set_auth_user(char *username)
 {
-       char *password;
+       const char *password;
+       char *p;
        fstring user, domain;
 
        /* Separate into user and password */
 
        parse_wbinfo_domain_user(username, domain, user);
 
-       password = strchr(user, '%');
+       p = strchr(user, '%');
 
-       if (password) {
-               *password = 0;
-               password++;
+       if (p != NULL) {
+               *p = 0;
+               password = p+1;
        } else {
                char *thepass = getpass("Password: ");
                if (thepass) {
-                       password = thepass;     
+                       password = thepass;
                } else
                        password = "";
        }
@@ -875,7 +1249,7 @@ static BOOL wbinfo_set_auth_user(char *username)
                if (!secrets_store(SECRETS_AUTH_USER, user,
                                   strlen(user) + 1)) {
                        d_fprintf(stderr, "error storing username\n");
-                       return False;
+                       return false;
                }
 
                /* We always have a domain name added by the
@@ -884,7 +1258,7 @@ static BOOL wbinfo_set_auth_user(char *username)
                if (!secrets_store(SECRETS_AUTH_DOMAIN, domain,
                                   strlen(domain) + 1)) {
                        d_fprintf(stderr, "error storing domain name\n");
-                       return False;
+                       return false;
                }
 
        } else {
@@ -897,13 +1271,13 @@ static BOOL wbinfo_set_auth_user(char *username)
                if (!secrets_store(SECRETS_AUTH_PASSWORD, password,
                                   strlen(password) + 1)) {
                        d_fprintf(stderr, "error storing password\n");
-                       return False;
+                       return false;
                }
 
        } else
                secrets_delete(SECRETS_AUTH_PASSWORD);
 
-       return True;
+       return true;
 }
 
 static void wbinfo_get_auth_user(void)
@@ -911,7 +1285,7 @@ static void wbinfo_get_auth_user(void)
        char *user, *domain, *password;
 
        /* Lift data from secrets file */
-       
+
        secrets_fetch_ipc_userpass(&user, &domain, &password);
 
        if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){
@@ -933,18 +1307,18 @@ static void wbinfo_get_auth_user(void)
        SAFE_FREE(password);
 }
 
-static BOOL wbinfo_ping(void)
+static bool wbinfo_ping(void)
 {
-        NSS_STATUS result;
+       wbcErr wbc_status;
 
-       result = winbindd_request(WINBINDD_PING, NULL, NULL);
+       wbc_status = wbcPing();
 
        /* Display response */
 
-        d_printf("Ping to winbindd %s on fd %d\n", 
-               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
+       d_printf("Ping to winbindd %s\n",
+                WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
 
-        return result == NSS_STATUS_SUCCESS;
+       return WBC_ERROR_IS_OK(wbc_status);
 }
 
 /* Main program */
@@ -954,23 +1328,36 @@ enum {
        OPT_GET_AUTH_USER,
        OPT_DOMAIN_NAME,
        OPT_SEQUENCE,
-       OPT_USERSIDS
+       OPT_GETDCNAME,
+       OPT_DSGETDCNAME,
+       OPT_USERDOMGROUPS,
+       OPT_USERSIDS,
+       OPT_ALLOCATE_UID,
+       OPT_ALLOCATE_GID,
+       OPT_SEPARATOR,
+       OPT_LIST_ALL_DOMAINS,
+       OPT_LIST_OWN_DOMAIN,
+       OPT_UID_INFO,
+       OPT_GROUP_INFO,
+       OPT_VERBOSE,
+       OPT_ONLINESTATUS
 };
 
-int main(int argc, char **argv)
+int main(int argc, char **argv, char **envp)
 {
        int opt;
-
+       TALLOC_CTX *frame = talloc_stackframe();
        poptContext pc;
        static char *string_arg;
        static char *opt_domain_name;
        static int int_arg;
        int result = 1;
+       bool verbose = false;
 
        struct poptOption long_options[] = {
                POPT_AUTOHELP
 
-               /* longName, shortName, argInfo, argPtr, value, descrip, 
+               /* longName, shortName, argInfo, argPtr, value, descrip,
                   argDesc */
 
                { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"},
@@ -979,43 +1366,55 @@ int main(int argc, char **argv)
                { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" },
                { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" },
                { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" },
+               { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" },
                { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" },
                { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
                { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
                { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
-               { "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" },
-               { "delete-user", 'x', POPT_ARG_STRING, &string_arg, 'x', "Delete a local user account", "name" },
-               { "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
-               { "delete-group", 'X', POPT_ARG_STRING, &string_arg, 'X', "Delete a local group", "name" },
-               { "add-to-group", 'o', POPT_ARG_STRING, &string_arg, 'o', "Add user to group", "user:group" },
-               { "del-from-group", 'O', POPT_ARG_STRING, &string_arg, 'O', "Remove user from group", "user:group" },
+               { "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID,
+                 "Get a new UID out of idmap" },
+               { "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID,
+                 "Get a new GID out of idmap" },
                { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
                { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
+               { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
+               { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" },
                { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
+               { "online-status", 0, POPT_ARG_NONE, 0, OPT_ONLINESTATUS, "Show whether domains are marked as online or offline"},
                { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
+               { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
+               { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" },
+               { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
                { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
+               { "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
+                 OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
                { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
                { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
                { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" },
+               { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
+                 "Get a DC name for a foreign domain", "domainname" },
+               { "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" },
                { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL },
                { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
                { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
+#ifdef WITH_FAKE_KASERVER
+               { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
+#endif
+#ifdef HAVE_KRB5
+               { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
+                       /* destroys wbinfo --help output */
+                       /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
+#endif
+               { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
+               { "verbose", 0, POPT_ARG_NONE, 0, OPT_VERBOSE, "Print additional information per command", NULL },
+               POPT_COMMON_CONFIGFILE
                POPT_COMMON_VERSION
                POPT_TABLEEND
        };
 
        /* Samba client initialisation */
+       load_case_tables();
 
-       if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
-               d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
-                       dyn_CONFIGFILE, strerror(errno));
-               exit(1);
-       }
-
-       if (!init_names())
-               return 1;
-
-       load_interfaces();
 
        /* Parse options */
 
@@ -1030,10 +1429,26 @@ int main(int argc, char **argv)
 
        while((opt = poptGetNextOpt(pc)) != -1) {
                /* get the generic configuration parameters like --domain */
+               switch (opt) {
+               case OPT_VERBOSE:
+                       verbose = True;
+                       break;
+               }
        }
 
        poptFreeContext(pc);
 
+       if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, true)) {
+               d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
+                       get_dyn_CONFIGFILE(), strerror(errno));
+               exit(1);
+       }
+
+       if (!init_names())
+               return 1;
+
+       load_interfaces();
+
        pc = poptGetContext(NULL, argc, (const char **)argv, long_options, 
                            POPT_CONTEXT_KEEP_FIRST);
 
@@ -1041,175 +1456,242 @@ int main(int argc, char **argv)
                switch (opt) {
                case 'u':
                        if (!print_domain_users(opt_domain_name)) {
-                               d_printf("Error looking up domain users\n");
+                               d_fprintf(stderr, "Error looking up domain users\n");
                                goto done;
                        }
                        break;
                case 'g':
                        if (!print_domain_groups(opt_domain_name)) {
-                               d_printf("Error looking up domain groups\n");
+                               d_fprintf(stderr, "Error looking up domain groups\n");
                                goto done;
                        }
                        break;
                case 's':
                        if (!wbinfo_lookupsid(string_arg)) {
-                               d_printf("Could not lookup sid %s\n", string_arg);
+                               d_fprintf(stderr, "Could not lookup sid %s\n", string_arg);
+                               goto done;
+                       }
+                       break;
+               case 'R':
+                       if (!wbinfo_lookuprids(opt_domain_name, string_arg)) {
+                               d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg);
                                goto done;
                        }
                        break;
                case 'n':
                        if (!wbinfo_lookupname(string_arg)) {
-                               d_printf("Could not lookup name %s\n", string_arg);
+                               d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
                                goto done;
                        }
                        break;
                case 'N':
                        if (!wbinfo_wins_byname(string_arg)) {
-                               d_printf("Could not lookup WINS by name %s\n", string_arg);
+                               d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg);
                                goto done;
                        }
                        break;
                case 'I':
                        if (!wbinfo_wins_byip(string_arg)) {
-                               d_printf("Could not lookup WINS by IP %s\n", string_arg);
+                               d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg);
                                goto done;
                        }
                        break;
                case 'U':
                        if (!wbinfo_uid_to_sid(int_arg)) {
-                               d_printf("Could not convert uid %d to sid\n", int_arg);
+                               d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg);
                                goto done;
                        }
                        break;
                case 'G':
                        if (!wbinfo_gid_to_sid(int_arg)) {
-                               d_printf("Could not convert gid %d to sid\n",
+                               d_fprintf(stderr, "Could not convert gid %d to sid\n",
                                       int_arg);
                                goto done;
                        }
                        break;
                case 'S':
                        if (!wbinfo_sid_to_uid(string_arg)) {
-                               d_printf("Could not convert sid %s to uid\n",
+                               d_fprintf(stderr, "Could not convert sid %s to uid\n",
                                       string_arg);
                                goto done;
                        }
                        break;
                case 'Y':
                        if (!wbinfo_sid_to_gid(string_arg)) {
-                               d_printf("Could not convert sid %s to gid\n",
+                               d_fprintf(stderr, "Could not convert sid %s to gid\n",
                                       string_arg);
                                goto done;
                        }
                        break;
+               case OPT_ALLOCATE_UID:
+                       if (!wbinfo_allocate_uid()) {
+                               d_fprintf(stderr, "Could not allocate a uid\n");
+                               goto done;
+                       }
+                       break;
+               case OPT_ALLOCATE_GID:
+                       if (!wbinfo_allocate_gid()) {
+                               d_fprintf(stderr, "Could not allocate a gid\n");
+                               goto done;
+                       }
+                       break;
                case 't':
                        if (!wbinfo_check_secret()) {
-                               d_printf("Could not check secret\n");
+                               d_fprintf(stderr, "Could not check secret\n");
                                goto done;
                        }
                        break;
                case 'm':
-                       if (!wbinfo_list_domains()) {
-                               d_printf("Could not list trusted domains\n");
+                       if (!wbinfo_list_domains(false, verbose)) {
+                               d_fprintf(stderr, "Could not list trusted domains\n");
                                goto done;
                        }
                        break;
                case OPT_SEQUENCE:
                        if (!wbinfo_show_sequence(opt_domain_name)) {
-                               d_printf("Could not show sequence numbers\n");
+                               d_fprintf(stderr, "Could not show sequence numbers\n");
+                               goto done;
+                       }
+                       break;
+               case OPT_ONLINESTATUS:
+                       if (!wbinfo_show_onlinestatus(opt_domain_name)) {
+                               d_fprintf(stderr, "Could not show online-status\n");
                                goto done;
                        }
                        break;
                case 'D':
                        if (!wbinfo_domain_info(string_arg)) {
-                               d_printf("Could not get domain info\n");
+                               d_fprintf(stderr, "Could not get domain info\n");
+                               goto done;
+                       }
+                       break;
+               case 'i':
+                       if (!wbinfo_get_userinfo(string_arg)) {
+                               d_fprintf(stderr, "Could not get info for user %s\n",
+                                                 string_arg);
+                               goto done;
+                       }
+                       break;
+               case OPT_UID_INFO:
+                       if ( !wbinfo_get_uidinfo(int_arg)) {
+                               d_fprintf(stderr, "Could not get info for uid "
+                                               "%d\n", int_arg);
+                               goto done;
+                       }
+                       break;
+               case OPT_GROUP_INFO:
+                       if ( !wbinfo_get_groupinfo(string_arg)) {
+                               d_fprintf(stderr, "Could not get info for "
+                                         "group %s\n", string_arg);
                                goto done;
                        }
                        break;
                case 'r':
                        if (!wbinfo_get_usergroups(string_arg)) {
-                               d_printf("Could not get groups for user %s\n", 
+                               d_fprintf(stderr, "Could not get groups for user %s\n", 
                                       string_arg);
                                goto done;
                        }
                        break;
                case OPT_USERSIDS:
                        if (!wbinfo_get_usersids(string_arg)) {
-                               d_printf("Could not get group SIDs for user SID %s\n", 
+                               d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", 
                                       string_arg);
                                goto done;
                        }
                        break;
+               case OPT_USERDOMGROUPS:
+                       if (!wbinfo_get_userdomgroups(string_arg)) {
+                               d_fprintf(stderr, "Could not get user's domain groups "
+                                        "for user SID %s\n", string_arg);
+                               goto done;
+                       }
+                       break;
                case 'a': {
-                               BOOL got_error = False;
+                               bool got_error = false;
 
                                if (!wbinfo_auth(string_arg)) {
-                                       d_printf("Could not authenticate user %s with "
+                                       d_fprintf(stderr, "Could not authenticate user %s with "
                                                "plaintext password\n", string_arg);
-                                       got_error = True;
+                                       got_error = true;
                                }
 
                                if (!wbinfo_auth_crap(string_arg)) {
-                                       d_printf("Could not authenticate user %s with "
+                                       d_fprintf(stderr, "Could not authenticate user %s with "
                                                "challenge/response\n", string_arg);
-                                       got_error = True;
+                                       got_error = true;
                                }
 
                                if (got_error)
                                        goto done;
                                break;
                        }
-               case 'c':
-                       if ( !wbinfo_create_user(string_arg) ) {
-                               d_printf("Could not create user account\n");
+               case 'K': {
+                               uint32 flags =  WBFLAG_PAM_KRB5 |
+                                               WBFLAG_PAM_CACHED_LOGIN |
+                                               WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
+                                               WBFLAG_PAM_INFO3_TEXT;
+
+                               if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) {
+                                       d_fprintf(stderr, "Could not authenticate user [%s] with "
+                                               "Kerberos (ccache: %s)\n", string_arg, "FILE");
+                                       goto done;
+                               }
+                               break;
+                       }
+               case 'k':
+                       if (!wbinfo_klog(string_arg)) {
+                               d_fprintf(stderr, "Could not klog user\n");
                                goto done;
                        }
                        break;
-               case 'C':
-                       if ( !wbinfo_create_group(string_arg) ) {
-                               d_printf("Could not create group\n");
+               case 'p':
+                       if (!wbinfo_ping()) {
+                               d_fprintf(stderr, "could not ping winbindd!\n");
                                goto done;
                        }
                        break;
-               case 'o':
-                       if ( !wbinfo_add_user_to_group(string_arg) ) {
-                               d_printf("Could not add user to group\n");
+               case OPT_SET_AUTH_USER:
+                       if (!wbinfo_set_auth_user(string_arg)) {
                                goto done;
                        }
                        break;
-               case 'O':
-                       if ( !wbinfo_remove_user_from_group(string_arg) ) {
-                               d_printf("Could not remove user from group\n");
+               case OPT_GET_AUTH_USER:
+                       wbinfo_get_auth_user();
+                       break;
+               case OPT_GETDCNAME:
+                       if (!wbinfo_getdcname(string_arg)) {
                                goto done;
                        }
                        break;
-               case 'x':
-                       if ( !wbinfo_delete_user(string_arg) ) {
-                               d_printf("Could not delete user account\n");
+               case OPT_DSGETDCNAME:
+                       if (!wbinfo_dsgetdcname(string_arg, 0)) {
                                goto done;
                        }
                        break;
-               case 'X':
-                       if ( !wbinfo_delete_group(string_arg) ) {
-                               d_printf("Could not delete group\n");
+               case OPT_SEPARATOR: {
+                       const char sep = winbind_separator_int(true);
+                       if ( !sep ) {
                                goto done;
                        }
+                       d_printf("%c\n", sep);
                        break;
-               case 'p':
-                       if (!wbinfo_ping()) {
-                               d_printf("could not ping winbindd!\n");
+               }
+               case OPT_LIST_ALL_DOMAINS:
+                       if (!wbinfo_list_domains(true, verbose)) {
                                goto done;
                        }
                        break;
-               case OPT_SET_AUTH_USER:
-                       wbinfo_set_auth_user(string_arg);
-                       break;
-               case OPT_GET_AUTH_USER:
-                       wbinfo_get_auth_user();
+               case OPT_LIST_OWN_DOMAIN:
+                       if (!wbinfo_list_own_domain()) {
+                               goto done;
+                       }
                        break;
                /* generic configuration options */
                case OPT_DOMAIN_NAME:
                        break;
+               case OPT_VERBOSE:
+                       break;
                default:
                        d_fprintf(stderr, "Invalid option\n");
                        poptPrintHelp(pc, stderr, 0);
@@ -1222,6 +1704,8 @@ int main(int argc, char **argv)
        /* Exit code */
 
  done:
+       talloc_destroy(frame);
+
        poptFreeContext(pc);
        return result;
 }