1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/source3/nsswitch/wbinfo.c
Andrew Bartlett 7d6dd0b3a0 Return the winbind separator over the socket, so programs don't have to parse
smb.conf to get it right.

While wb_client needs its lp_load() for samba dependency reasons, it now uses
the new method both to example and test the new code.

Also add an interface version function, and return the winbind's samba version
string.

In preperation for default domains, its now up to winbindd to reject plaintext
auths that don't have a seperator, but NTLM (CRAP) auths now have two feilds,
hence need parsing.

Andrew Bartlett
(This used to be commit 2bd2a092ee)
2002-01-10 11:28:14 +00:00

729 lines
16 KiB
C

/*
Unix SMB/Netbios implementation.
Version 2.0
Winbind status program.
Copyright (C) Tim Potter 2000
Copyright (C) Andrew Bartlett 2002
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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.
*/
#include "includes.h"
#include "winbindd.h"
#include "debug.h"
/* Prototypes from common.h */
NSS_STATUS winbindd_request(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
static char get_winbind_separator(void)
{
struct winbindd_response response;
char winbind_separator;
ZERO_STRUCT(response);
/* Send off request */
if (winbindd_request(WINBINDD_INFO, NULL, &response) !=
NSS_STATUS_SUCCESS) {
printf("could not obtain winbind seperator!\n");
exit(1);
}
winbind_separator = response.data.info.winbind_separator;
if (!winbind_separator) {
printf("winbind separator was NULL!\n");
exit(1);
}
return winbind_separator;
}
/* 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, fstring user)
{
char *p = strchr(domuser,get_winbind_separator());
if (!p)
return False;
fstrcpy(user, p+1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
strupper(domain);
return True;
}
/* List groups a user is a member of */
static BOOL wbinfo_get_usergroups(char *user)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
int i;
ZERO_STRUCT(response);
/* Send request */
fstrcpy(request.data.username, user);
result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
if (result != NSS_STATUS_SUCCESS) {
return False;
}
for (i = 0; i < response.data.num_entries; i++) {
printf("%d\n", (int)((gid_t *)response.extra_data)[i]);
}
return True;
}
/* List trusted domains */
static BOOL wbinfo_list_domains(void)
{
struct winbindd_response response;
fstring name;
ZERO_STRUCT(response);
/* Send request */
if (winbindd_request(WINBINDD_LIST_TRUSTDOM, NULL, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
if (response.extra_data) {
while(next_token((char **)&response.extra_data, name, ",",
sizeof(fstring))) {
printf("%s\n", name);
}
}
return True;
}
/* Check trust account password */
static BOOL wbinfo_check_secret(void)
{
struct winbindd_response response;
BOOL result;
ZERO_STRUCT(response);
result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response) ==
NSS_STATUS_SUCCESS;
if (result) {
if (response.data.num_entries == 0) {
printf("Secret is good\n");
} else {
printf("Secret is bad\n0x%08x\n",
response.data.num_entries);
}
return True;
}
return False;
}
/* Convert uid to sid */
static BOOL wbinfo_uid_to_sid(uid_t uid)
{
struct winbindd_request request;
struct winbindd_response response;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send request */
request.data.uid = uid;
if (winbindd_request(WINBINDD_UID_TO_SID, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%s\n", response.data.sid.sid);
return True;
}
/* Convert gid to sid */
static BOOL wbinfo_gid_to_sid(gid_t gid)
{
struct winbindd_request request;
struct winbindd_response response;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send request */
request.data.gid = gid;
if (winbindd_request(WINBINDD_GID_TO_SID, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%s\n", response.data.sid.sid);
return True;
}
/* Convert sid to uid */
static BOOL wbinfo_sid_to_uid(char *sid)
{
struct winbindd_request request;
struct winbindd_response response;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send request */
fstrcpy(request.data.sid, sid);
if (winbindd_request(WINBINDD_SID_TO_UID, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%d\n", (int)response.data.uid);
return True;
}
static BOOL wbinfo_sid_to_gid(char *sid)
{
struct winbindd_request request;
struct winbindd_response response;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send request */
fstrcpy(request.data.sid, sid);
if (winbindd_request(WINBINDD_SID_TO_GID, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%d\n", (int)response.data.gid);
return True;
}
/* Convert sid to string */
static BOOL wbinfo_lookupsid(char *sid)
{
struct winbindd_request request;
struct winbindd_response response;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send off request */
fstrcpy(request.data.sid, sid);
if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%s %d\n", response.data.name.name, response.data.name.type);
return True;
}
/* Convert string to sid */
static BOOL wbinfo_lookupname(char *name)
{
struct winbindd_request request;
struct winbindd_response response;
/*
* Don't do the lookup if the name has no separator.
*/
if (!strchr(name, get_winbind_separator()))
return False;
/* Send off request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
fstrcpy(request.data.name, name);
if (winbindd_request(WINBINDD_LOOKUPNAME, &request, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Display response */
printf("%s %d\n", response.data.sid.sid, response.data.sid.type);
return True;
}
/* Authenticate a user with a plaintext password */
static BOOL wbinfo_auth(char *username)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
char *p;
/* Send off request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
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);
result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response);
/* Display response */
printf("plaintext password authentication %s\n",
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
return result == NSS_STATUS_SUCCESS;
}
/* Authenticate a user with a challenge/response */
static BOOL wbinfo_auth_crap(char *username)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
fstring name_user;
fstring name_domain;
fstring pass;
char *p;
char sep = get_winbind_separator();
/*
* Don't do the lookup if the name has no separator.
*/
if (!strchr(username, sep)) {
printf("no domain seperator (%c) in username - failing\n", sep);
return False;
}
/* 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);
fstrcpy(request.data.auth_crap.user, name_user);
fstrcpy(request.data.auth_crap.domain, name_domain);
generate_random_buffer(request.data.auth_crap.chal, 8, False);
SMBencrypt((uchar *)pass, request.data.auth_crap.chal,
(uchar *)request.data.auth_crap.lm_resp);
SMBNTencrypt((uchar *)pass, request.data.auth_crap.chal,
(uchar *)request.data.auth_crap.nt_resp);
request.data.auth_crap.lm_resp_len = 24;
request.data.auth_crap.nt_resp_len = 24;
result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
/* Display response */
printf("challenge/response password authentication %s\n",
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
return result == NSS_STATUS_SUCCESS;
}
/* Print domain users */
static BOOL print_domain_users(void)
{
struct winbindd_response response;
fstring name;
/* Send request to winbind daemon */
ZERO_STRUCT(response);
if (winbindd_request(WINBINDD_LIST_USERS, NULL, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Look through extra data */
if (!response.extra_data) {
return False;
}
while(next_token((char **)&response.extra_data, name, ",",
sizeof(fstring))) {
printf("%s\n", name);
}
return True;
}
/* Print domain groups */
static BOOL print_domain_groups(void)
{
struct winbindd_response response;
fstring name;
ZERO_STRUCT(response);
if (winbindd_request(WINBINDD_LIST_GROUPS, NULL, &response) !=
NSS_STATUS_SUCCESS) {
return False;
}
/* Look through extra data */
if (!response.extra_data) {
return False;
}
while(next_token((char **)&response.extra_data, name, ",",
sizeof(fstring))) {
printf("%s\n", name);
}
return True;
}
/* Set the authorised user for winbindd access in secrets.tdb */
static BOOL wbinfo_set_auth_user(char *username)
{
char *password;
/* Separate into user and password */
password = strchr(username, '%');
if (password) {
*password = 0;
password++;
} else
password = "";
/* Store in secrets.tdb */
if (!secrets_store(SECRETS_AUTH_USER, username, strlen(username) + 1) ||
!secrets_store(SECRETS_AUTH_PASSWORD, password, strlen(password) + 1)) {
fprintf(stderr, "error storing authenticated user info\n");
return False;
}
return True;
}
static BOOL wbinfo_ping(void)
{
NSS_STATUS result;
result = winbindd_request(WINBINDD_PING, NULL, NULL);
/* Display response */
printf("'ping' to winbindd %s\n",
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
return result == NSS_STATUS_SUCCESS;
}
/* Print program usage */
static void usage(void)
{
printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm "
"| -a user%%password\n");
printf("\t-u\t\t\tlists all domain users\n");
printf("\t-g\t\t\tlists all domain groups\n");
printf("\t-n name\t\t\tconverts name to sid\n");
printf("\t-s sid\t\t\tconverts sid to name\n");
printf("\t-U uid\t\t\tconverts uid to sid\n");
printf("\t-G gid\t\t\tconverts gid to sid\n");
printf("\t-S sid\t\t\tconverts sid to uid\n");
printf("\t-Y sid\t\t\tconverts sid to gid\n");
printf("\t-t\t\t\tcheck shared secret\n");
printf("\t-m\t\t\tlist trusted domains\n");
printf("\t-r user\t\t\tget user groups\n");
printf("\t-a user%%password\tauthenticate user\n");
printf("\t-p 'ping' winbindd to see if it is alive\n");
}
/* Main program */
enum {
OPT_SET_AUTH_USER = 1000
};
int main(int argc, char **argv)
{
extern pstring global_myname;
int opt;
poptContext pc;
static char *string_arg;
static int int_arg;
BOOL got_command = False;
struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{ "help", 'h', POPT_ARG_NONE, 0, 'h' },
{ "domain-users", 'u', POPT_ARG_NONE, 0, 'u' },
{ "domain-groups", 'g', POPT_ARG_NONE, 0, 'g' },
{ "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n' },
{ "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's' },
{ "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U' },
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G' },
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S' },
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y' },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't' },
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm' },
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r' },
{ "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a' },
{ "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER },
{ "ping", 'p', POPT_ARG_NONE, 0, 'p' },
{ 0, 0, 0, 0 }
};
/* Samba client initialisation */
if (!*global_myname) {
char *p;
fstrcpy(global_myname, myhostname());
p = strchr(global_myname, '.');
if (p) {
*p = 0;
}
}
if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
dyn_CONFIGFILE, strerror(errno));
exit(1);
}
load_interfaces();
/* Parse command line options */
if (argc == 1) {
usage();
return 1;
}
/* Parse options */
pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
while((opt = poptGetNextOpt(pc)) != -1) {
if (got_command) {
fprintf(stderr, "No more than one command may be specified "
"at once.\n");
exit(1);
}
got_command = True;
}
pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
POPT_CONTEXT_KEEP_FIRST);
while((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case 'h':
usage();
exit(0);
case 'u':
if (!print_domain_users()) {
printf("Error looking up domain users\n");
return 1;
}
break;
case 'g':
if (!print_domain_groups()) {
printf("Error looking up domain groups\n");
return 1;
}
break;
case 's':
if (!wbinfo_lookupsid(string_arg)) {
printf("Could not lookup sid %s\n", string_arg);
return 1;
}
break;
case 'n':
if (!wbinfo_lookupname(string_arg)) {
printf("Could not lookup name %s\n", string_arg);
return 1;
}
break;
case 'U':
if (!wbinfo_uid_to_sid(int_arg)) {
printf("Could not convert uid %d to sid\n", int_arg);
return 1;
}
break;
case 'G':
if (!wbinfo_gid_to_sid(int_arg)) {
printf("Could not convert gid %d to sid\n",
int_arg);
return 1;
}
break;
case 'S':
if (!wbinfo_sid_to_uid(string_arg)) {
printf("Could not convert sid %s to uid\n",
string_arg);
return 1;
}
break;
case 'Y':
if (!wbinfo_sid_to_gid(string_arg)) {
printf("Could not convert sid %s to gid\n",
string_arg);
return 1;
}
break;
case 't':
if (!wbinfo_check_secret()) {
printf("Could not check secret\n");
return 1;
}
break;
case 'm':
if (!wbinfo_list_domains()) {
printf("Could not list trusted domains\n");
return 1;
}
break;
case 'r':
if (!wbinfo_get_usergroups(string_arg)) {
printf("Could not get groups for user %s\n",
string_arg);
return 1;
}
break;
case 'a': {
BOOL got_error = False;
if (!wbinfo_auth(string_arg)) {
printf("Could not authenticate user %s with "
"plaintext password\n", string_arg);
got_error = True;
}
if (!wbinfo_auth_crap(string_arg)) {
printf("Could not authenticate user %s with "
"challenge/response\n", string_arg);
got_error = True;
}
if (got_error)
return 1;
break;
}
case 'p': {
if (!wbinfo_ping()) {
printf("could not ping winbindd!\n");
return 1;
}
break;
}
case OPT_SET_AUTH_USER:
if (!(wbinfo_set_auth_user(string_arg))) {
return 1;
}
break;
default:
fprintf(stderr, "Invalid option\n");
usage();
return 1;
}
}
/* Clean exit */
return 0;
}