summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/debug2html.c253
-rw-r--r--source3/utils/make_printerdef.c585
-rw-r--r--source3/utils/net.c458
-rw-r--r--source3/utils/net.h51
-rw-r--r--source3/utils/net_ads.c787
-rw-r--r--source3/utils/net_help.c126
-rw-r--r--source3/utils/net_lookup.c61
-rw-r--r--source3/utils/net_rap.c1084
-rw-r--r--source3/utils/net_rpc.c1328
-rw-r--r--source3/utils/net_rpc_join.c303
-rw-r--r--source3/utils/net_time.c185
-rw-r--r--source3/utils/nmblookup.c299
-rw-r--r--source3/utils/pdbedit.c692
-rw-r--r--source3/utils/rpccheck.c62
-rw-r--r--source3/utils/smbcacls.c964
-rw-r--r--source3/utils/smbcontrol.c509
-rw-r--r--source3/utils/smbfilter.c246
-rw-r--r--source3/utils/smbgroupedit.c397
-rw-r--r--source3/utils/smbpasswd.c973
-rw-r--r--source3/utils/smbtree.c423
-rw-r--r--source3/utils/smbw_sample.c94
-rw-r--r--source3/utils/status.c846
-rw-r--r--source3/utils/testparm.c295
-rw-r--r--source3/utils/testprns.c22
24 files changed, 10259 insertions, 784 deletions
diff --git a/source3/utils/debug2html.c b/source3/utils/debug2html.c
new file mode 100644
index 0000000000..f9a1f43f46
--- /dev/null
+++ b/source3/utils/debug2html.c
@@ -0,0 +1,253 @@
+/* ========================================================================== **
+ * debug2html.c
+ *
+ * Copyright (C) 1998 by Christopher R. Hertel
+ *
+ * Email: crh@ubiqx.mn.org
+ *
+ * -------------------------------------------------------------------------- **
+ * Parse Samba debug logs (2.0 & greater) and output the results as HTML.
+ * -------------------------------------------------------------------------- **
+ *
+ * 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.
+ *
+ * -------------------------------------------------------------------------- **
+ * This program provides an example of the use of debugparse.c, and also
+ * does a decent job of converting Samba logs into HTML.
+ * -------------------------------------------------------------------------- **
+ *
+ * Revision 1.4 1998/11/13 03:37:01 tridge
+ * fixes for OSF1 compilation
+ *
+ * Revision 1.3 1998/10/28 20:33:35 crh
+ * I've moved the debugparse module files into the ubiqx directory because I
+ * know that 'make proto' will ignore them there. The debugparse.h header
+ * file is included in includes.h, and includes.h is included in debugparse.c,
+ * so all of the pieces "see" each other. I've compiled and tested this,
+ * and it does seem to work. It's the same compromise model I used when
+ * adding the ubiqx modules into the system, which is why I put it all into
+ * the same directory.
+ *
+ * Chris -)-----
+ *
+ * Revision 1.1 1998/10/26 23:21:37 crh
+ * Here is the simple debug parser and the debug2html converter. Still to do:
+ *
+ * * Debug message filtering.
+ * * I need to add all this to Makefile.in
+ * (If it looks at all strange I'll ask for help.)
+ *
+ * If you want to compile debug2html, you'll need to do it by hand until I
+ * make the changes to Makefile.in. Sorry.
+ *
+ * Chris -)-----
+ *
+ * ========================================================================== **
+ */
+
+#include "debugparse.h"
+
+/* -------------------------------------------------------------------------- **
+ * The size of the read buffer.
+ */
+
+#define DBG_BSIZE 1024
+
+/* -------------------------------------------------------------------------- **
+ * Functions...
+ */
+
+static dbg_Token modechange( dbg_Token new, dbg_Token mode )
+ /* ------------------------------------------------------------------------ **
+ * Handle a switch between header and message printing.
+ *
+ * Input: new - The token value of the current token. This indicates
+ * the lexical item currently being recognized.
+ * mode - The current mode. This is either dbg_null or
+ * dbg_message. It could really be any toggle
+ * (true/false, etc.)
+ *
+ * Output: The new mode. This will be the same as the input mode unless
+ * there was a transition in or out of message processing.
+ *
+ * Notes: The purpose of the mode value is to mark the beginning and end
+ * of the message text block. In order to show the text in its
+ * correct format, it must be included within a <PRE></PRE> block.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ switch( new )
+ {
+ case dbg_null:
+ case dbg_ignore:
+ return( mode );
+ case dbg_message:
+ if( dbg_message != mode )
+ {
+ /* Switching to message mode. */
+ (void)printf( "<PRE>\n" );
+ return( dbg_message );
+ }
+ break;
+ default:
+ if( dbg_message == mode )
+ {
+ /* Switching out of message mode. */
+ (void)printf( "</PRE>\n\n" );
+ return( dbg_null );
+ }
+ }
+
+ return( mode );
+ } /* modechange */
+
+static void newblock( dbg_Token old, dbg_Token new )
+ /* ------------------------------------------------------------------------ **
+ * Handle the transition between tokens.
+ *
+ * Input: old - The previous token.
+ * new - The current token.
+ *
+ * Output: none.
+ *
+ * Notes: This is called whenever there is a transition from one token
+ * type to another. It first prints the markup tags that close
+ * the previous token, and then the markup tags for the new
+ * token.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ switch( old )
+ {
+ case dbg_timestamp:
+ (void)printf( ",</B>" );
+ break;
+ case dbg_level:
+ (void)printf( "</FONT>]</B>\n " );
+ break;
+ case dbg_sourcefile:
+ (void)printf( ":" );
+ break;
+ case dbg_lineno:
+ (void)printf( ")" );
+ break;
+ }
+
+ switch( new )
+ {
+ case dbg_timestamp:
+ (void)printf( "<B>[" );
+ break;
+ case dbg_level:
+ (void)printf( " <B><FONT COLOR=MAROON>" );
+ break;
+ case dbg_lineno:
+ (void)printf( "(" );
+ break;
+ }
+ } /* newblock */
+
+static void charprint( dbg_Token tok, int c )
+ /* ------------------------------------------------------------------------ **
+ * Filter the input characters to determine what goes to output.
+ *
+ * Input: tok - The token value of the current character.
+ * c - The current character.
+ *
+ * Output: none.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ switch( tok )
+ {
+ case dbg_ignore:
+ case dbg_header:
+ break;
+ case dbg_null:
+ case dbg_eof:
+ (void)putchar( '\n' );
+ break;
+ default:
+ switch( c )
+ {
+ case '<':
+ (void)printf( "&lt;" );
+ break;
+ case '>':
+ (void)printf( "&gt;" );
+ break;
+ case '&':
+ (void)printf( "&amp;" );
+ break;
+ case '\"':
+ (void)printf( "&#34;" );
+ break;
+ default:
+ (void)putchar( c );
+ break;
+ }
+ }
+ } /* charprint */
+
+int main( int argc, char *argv[] )
+ /* ------------------------------------------------------------------------ **
+ * This simple program scans and parses Samba debug logs, and produces HTML
+ * output.
+ *
+ * Input: argc - Currently ignored.
+ * argv - Currently ignored.
+ *
+ * Output: Always zero.
+ *
+ * Notes: The HTML output is sent to stdout.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ int i;
+ int len;
+ char bufr[DBG_BSIZE];
+ dbg_Token old = dbg_null,
+ new = dbg_null,
+ state = dbg_null,
+ mode = dbg_null;
+
+ (void)printf( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n" );
+ (void)printf( "<HTML>\n<HEAD>\n" );
+ (void)printf( " <TITLE>Samba Debug Output</TITLE>\n</HEAD>\n\n<BODY>\n" );
+
+ while( (!feof( stdin ))
+ && ((len = fread( bufr, 1, DBG_BSIZE, stdin )) > 0) )
+ {
+ for( i = 0; i < len; i++ )
+ {
+ old = new;
+ new = dbg_char2token( &state, bufr[i] );
+ if( new != old )
+ {
+ mode = modechange( new, mode );
+ newblock( old, new );
+ }
+ charprint( new, bufr[i] );
+ }
+ }
+ (void)modechange( dbg_eof, mode );
+
+ (void)printf( "</BODY>\n</HTML>\n" );
+ return( 0 );
+ } /* main */
diff --git a/source3/utils/make_printerdef.c b/source3/utils/make_printerdef.c
new file mode 100644
index 0000000000..35ecd7f3e9
--- /dev/null
+++ b/source3/utils/make_printerdef.c
@@ -0,0 +1,585 @@
+ /*
+ Unix SMB/CIFS implementation.
+ Create printer definition files.
+
+ Copyright (C) Jean-Francois.Micouleau@utc.fr, 10/26/97 - 1998
+
+ 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"
+
+/*
+#define DEBUGIT
+*/
+
+char *files_to_copy;
+char *driverfile, *datafile, *helpfile, *languagemonitor, *datatype, *vendorsetup;
+char buffer[50][sizeof(pstring)];
+char sbuffer[50][sizeof(pstring)];
+char sub_dir[50][2][sizeof(pstring)];
+
+static void usage(char *name)
+{
+ fprintf(stderr,"%s: printer.def \"Printer Name\"\n", name);
+}
+
+static char *myfgets(char *s, int n, FILE *stream)
+{
+ char *LString1;
+ char *LString2;
+ char *temp;
+ pstring String;
+ pstring NewString;
+ int i;
+
+ fgets(s,n,stream);
+ while ((LString1 = strchr_m(s,'%')) != NULL) {
+ if (!(LString2 = strchr_m(LString1+1,'%'))) break;
+ *LString2 = '\0';
+ pstrcpy(String,LString1+1);
+ i = 0;
+ while(*sbuffer[i]!='\0') {
+ if (strncmp(sbuffer[i],String,strlen(String))==0)
+ {
+ pstrcpy(String,sbuffer[i]);
+ if ((temp = strchr_m(String,'=')) != NULL) ++temp;
+ pstrcpy(String,temp);
+ break;
+ }
+ i++;
+ }
+ *LString1 = '\0';
+ pstrcpy(NewString,s);
+ pstrcat(NewString,String);
+ pstrcat(NewString,LString2+1);
+ pstrcpy(s, NewString);
+ }
+ return(s);
+}
+
+/*
+ This function split a line in two parts
+ on both side of the equal sign
+ "entry=value"
+*/
+static char *scan(char *chaine,char **entry)
+{
+ char *value;
+ char *temp;
+ int i=0;
+
+ *entry=(char *)malloc(sizeof(pstring));
+ value=(char *)malloc(sizeof(pstring));
+
+ if(*entry == NULL || value == NULL) {
+ fprintf(stderr,"scan: malloc fail !\n");
+ exit(1);
+ }
+
+ pstrcpy(*entry,chaine);
+ temp=chaine;
+ while( temp[i]!='=' && temp[i]!='\0') {
+ i++;
+ }
+ (*entry)[i]='\0';
+ if (temp[i]!='\0') {
+ i++;
+ }
+ while( temp[i]==' ' && temp[i]!='\0') {
+ i++;
+ }
+ pstrcpy(value,temp+i);
+ return (value);
+}
+
+static void build_subdir(void)
+{
+ int i=0;
+ int j=0;
+ char *entry;
+ char *data;
+
+ while (*buffer[i]!='\0') {
+ data=scan(buffer[i],&entry);
+#ifdef DEBUGIT
+ fprintf(stderr,"\tentry=data %s:%s\n",entry,data);
+#endif
+ j = strlen(entry);
+ while (j) {
+ if (entry[j-1] != ' ') break;
+ j--;
+ }
+ entry[j] = '\0';
+
+ if (strncmp(data,"11",2)==0) {
+ pstrcpy(sub_dir[i][0],entry);
+ pstrcpy(sub_dir[i][1],"");
+ }
+ if (strncmp(data,"23",2)==0) {
+ pstrcpy(sub_dir[i][0],entry);
+ pstrcpy(sub_dir[i][1],"color\\");
+ }
+#ifdef DEBUGIT
+ fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
+#endif
+ i++;
+ }
+}
+
+/*
+ Lockup Strings entry in a file
+ Return all the lines between the entry and the next one or the end of file
+ An entry is something between braces.
+*/
+static void lookup_strings(FILE *fichier)
+{
+ int found=0,pointeur=0,i=0;
+ char *temp,*temp2;
+
+ temp=(char *)malloc(sizeof(pstring));
+ temp2=(char *)malloc(sizeof(pstring));
+
+ if(temp == NULL || temp2 == NULL) {
+ SAFE_FREE(temp);
+ SAFE_FREE(temp2);
+ fprintf(stderr,"lookup_strings: malloc fail !\n");
+ exit(1);
+ }
+
+ *sbuffer[0]='\0';
+
+ pstrcpy(temp2,"[Strings]");
+
+ rewind(fichier);
+#ifdef DEBUGIT
+ fprintf(stderr,"\tLooking for Strings\n");
+#endif
+
+ while (!feof(fichier) && found==0) {
+ *temp='\0';
+ fgets(temp,255,fichier);
+ if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
+ }
+
+
+ while (!feof(fichier) && found==1) {
+ *temp='\0';
+ fgets(temp,255,fichier);
+ if (*temp=='[') {
+ found=2;
+ *sbuffer[pointeur]='\0';
+ }
+ else {
+ pstrcpy(sbuffer[pointeur],temp);
+ i=strlen(sbuffer[pointeur])-1;
+ while (sbuffer[pointeur][i]=='\r' || sbuffer[pointeur][i]=='\n')
+ sbuffer[pointeur][i--]='\0';
+ pointeur++;
+ }
+ }
+
+ /* CCMRCF Mod, seg fault or worse if not found */
+ if (pointeur == 0) {
+ fprintf(stderr,"Printer not found\tNo [Strings] block in inf file\n");
+ exit(2);
+ }
+
+#ifdef DEBUGIT
+ fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
+#endif
+}
+
+
+/*
+ Lockup an entry in a file
+ Return all the lines between the entry and the next one or the end of file
+ An entry is something between braces.
+*/
+static void lookup_entry(FILE *fichier,char *chaine)
+{
+ int found=0,pointeur=0,i=0;
+ char *temp,*temp2;
+
+ temp=(char *)malloc(sizeof(pstring));
+ temp2=(char *)malloc(sizeof(pstring));
+
+ if(temp == NULL || temp2 == NULL) {
+ SAFE_FREE(temp);
+ SAFE_FREE(temp2);
+ fprintf(stderr,"lookup_entry: malloc fail !\n");
+ exit(1);
+ }
+
+ *buffer[0]='\0';
+
+ pstrcpy(temp2,"[");
+ pstrcat(temp2,chaine);
+ pstrcat(temp2,"]");
+
+ rewind(fichier);
+#ifdef DEBUGIT
+ fprintf(stderr,"\tLooking for %s\n",chaine);
+#endif
+
+ while (!feof(fichier) && found==0) {
+ *temp='\0';
+ myfgets(temp,255,fichier);
+ if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
+ }
+
+
+ while (!feof(fichier) && found==1) {
+ *temp='\0';
+ myfgets(temp,255,fichier);
+ if (*temp=='[') {
+ found=2;
+ *buffer[pointeur]='\0';
+ }
+ else {
+ pstrcpy(buffer[pointeur],temp);
+ i=strlen(buffer[pointeur])-1;
+ while (buffer[pointeur][i]=='\r' || buffer[pointeur][i]=='\n')
+ buffer[pointeur][i--]='\0';
+ pointeur++;
+ }
+ }
+#ifdef DEBUGIT
+ fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
+#endif
+}
+
+static char *find_desc(FILE *fichier,char *text)
+{
+ char *chaine;
+ char *long_desc;
+ char *short_desc;
+ char *crap = NULL;
+ char *p;
+
+ int found=0;
+
+ chaine=(char *)malloc(sizeof(pstring));
+ long_desc=(char *)malloc(sizeof(pstring));
+ short_desc=(char *)malloc(sizeof(pstring));
+ if (!chaine || !long_desc || !short_desc) {
+ SAFE_FREE(chaine);
+ SAFE_FREE(long_desc);
+ SAFE_FREE(short_desc);
+ fprintf(stderr,"find_desc: Unable to malloc memory\n");
+ exit(1);
+ }
+
+ rewind(fichier);
+ while (!feof(fichier) && found==0)
+ {
+ myfgets(chaine,255,fichier);
+
+ long_desc=strtok(chaine,"=");
+ crap=strtok(NULL,",\r");
+
+ p=long_desc;
+ while(*p!='"' && *p!='\0')
+ p++;
+ if (*p=='"' && *(p+1)!='\0') p++;
+ long_desc=p;
+
+ if (*p!='\0')
+ {
+ p++;
+ while(*p!='\"')
+ p++;
+ *p='\0';
+ }
+ if (!strcmp(text,long_desc))
+ found=1;
+ }
+ SAFE_FREE(chaine);
+ if (!found || !crap) return(NULL);
+ while(*crap==' ') crap++;
+ pstrcpy(short_desc,crap);
+ return(short_desc);
+}
+
+static void scan_copyfiles(FILE *fichier, char *chaine)
+{
+ char *part;
+ char *mpart;
+ int i;
+ pstring direc;
+#ifdef DEBUGIT
+ fprintf(stderr,"In scan_copyfiles Lookup up of %s\n",chaine);
+#endif
+ fprintf(stderr,"\nCopy the following files to your printer$ share location:\n");
+ part=strtok(chaine,",");
+ do {
+ /* If the entry start with a @ then it's a file to copy
+ else it's an entry refering to files to copy
+ the main difference is when it's an entry
+ you can have a directory to append before the file name
+ */
+ if (*part=='@') {
+ if (strlen(files_to_copy) != 0)
+ pstrcat(files_to_copy,",");
+ pstrcat(files_to_copy,&part[1]);
+ fprintf(stderr,"%s\n",&part[1]);
+ } else {
+ lookup_entry(fichier,part);
+ i=0;
+ pstrcpy(direc,"");
+ while (*sub_dir[i][0]!='\0') {
+#ifdef DEBUGIT
+ fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
+#endif
+ if (strcmp(sub_dir[i][0],part)==0)
+ pstrcpy(direc,sub_dir[i][1]);
+ i++;
+ }
+ i=0;
+ while (*buffer[i]!='\0') {
+/*
+ * HP inf files have strange entries that this attempts to address
+ * Entries in the Copy sections normally have only a single file name
+ * on each line. I have seen the following format in various HP inf files:
+ *
+ * pscript.hlp = pscript.hl_
+ * hpdcmon.dll,hpdcmon.dl_
+ * MSVCRT.DLL,MSVCRT.DL_,,32
+ * ctl3dv2.dll,ctl3dv2.dl_,ctl3dv2.tmp
+ *
+ * In the first 2 cases you want the first file name - in the last case
+ * you only want the last file name (at least that is what a Win95
+ * machine sent). In the third case you also want the first file name
+ * (detect by the last component being just a number ?).
+ * This may still be wrong but at least I get the same list
+ * of files as seen on a printer test page.
+ */
+ part = strchr_m(buffer[i],'=');
+ if (part) {
+ /*
+ * Case (1) eg. pscript.hlp = pscript.hl_ - chop after the first name.
+ */
+
+ *part = '\0';
+
+ /*
+ * Now move back to the start and print that.
+ */
+
+ while (--part > buffer[i]) {
+ if ((*part == ' ') || (*part =='\t'))
+ *part = '\0';
+ else
+ break;
+ }
+ } else {
+ part = strchr_m(buffer[i],',');
+ if (part) {
+ /*
+ * Cases (2-4)
+ */
+
+ if ((mpart = strrchr_m(part+1,','))!=NULL) {
+ /*
+ * Second ',' - case 3 or 4.
+ * Check if the last part is just a number,
+ * if so we need the first part.
+ */
+
+ char *endptr = NULL;
+ BOOL isnumber = False;
+
+ mpart++;
+ (void)strtol(mpart, &endptr, 10);
+
+ isnumber = ((endptr > mpart) && isdigit(*mpart));
+ if(!isnumber)
+ pstrcpy(buffer[i],mpart+1);
+ else
+ *part = '\0';
+ } else {
+ *part = '\0';
+ }
+ while (--part > buffer[i])
+ if ((*part == ' ') || (*part =='\t')) *part = '\0';
+ else break;
+ }
+ }
+ if (*buffer[i] != ';') {
+ if (strlen(files_to_copy) != 0)
+ pstrcat(files_to_copy,",");
+ pstrcat(files_to_copy,direc);
+ pstrcat(files_to_copy,buffer[i]);
+ fprintf(stderr,"%s%s\n",direc,buffer[i]);
+ }
+ i++;
+ } /* end while */
+ }
+ part=strtok(NULL,",");
+ if (part) {
+ while( *part ==' ' && *part != '\0') {
+ part++;
+ }
+ }
+ } while (part!=NULL);
+ fprintf(stderr,"\n");
+}
+
+
+static void scan_short_desc(FILE *fichier, char *short_desc)
+{
+ int i=0;
+ char *temp;
+ char *copyfiles=0,*datasection=0;
+
+ helpfile=0;
+ languagemonitor=0;
+ vendorsetup=0;
+ datatype="RAW";
+ if((temp=(char *)malloc(sizeof(pstring))) == NULL) {
+ fprintf(stderr, "scan_short_desc: malloc fail !\n");
+ exit(1);
+ }
+
+ driverfile=short_desc;
+ datafile=short_desc;
+
+ lookup_entry(fichier,short_desc);
+
+ while(*buffer[i]!='\0') {
+#ifdef DEBUGIT
+ fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
+#endif
+ if (strncasecmp(buffer[i],"CopyFiles",9)==0)
+ copyfiles=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DataSection",11)==0)
+ datasection=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DataFile",8)==0)
+ datafile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DriverFile",10)==0)
+ driverfile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"HelpFile",8)==0)
+ helpfile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0)
+ languagemonitor=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DefaultDataType",15)==0)
+ datatype=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"VendorSetup",11)==0)
+ vendorsetup=scan(buffer[i],&temp);
+ i++;
+ }
+
+ if (datasection) {
+ lookup_entry(fichier,datasection);
+
+ i = 0;
+ while(*buffer[i]!='\0') {
+#ifdef DEBUGIT
+ fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
+#endif
+ if (strncasecmp(buffer[i],"CopyFiles",9)==0)
+ copyfiles=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DataSection",11)==0)
+ datasection=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DataFile",8)==0)
+ datafile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DriverFile",10)==0)
+ driverfile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"HelpFile",8)==0)
+ helpfile=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0)
+ languagemonitor=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"DefaultDataType",15)==0)
+ datatype=scan(buffer[i],&temp);
+ else if (strncasecmp(buffer[i],"VendorSetup",11)==0)
+ vendorsetup=scan(buffer[i],&temp);
+ i++;
+ }
+ }
+
+ if (languagemonitor) {
+ temp = strtok(languagemonitor,",");
+ if (*temp == '"') ++temp;
+ pstrcpy(languagemonitor,temp);
+ if ((temp = strchr_m(languagemonitor,'"'))!=NULL) *temp = '\0';
+ }
+
+ if (i) fprintf(stderr,"End of section found\n");
+
+ fprintf(stderr,"CopyFiles: %s\n",
+ copyfiles?copyfiles:"(null)");
+ fprintf(stderr,"Datasection: %s\n",
+ datasection?datasection:"(null)");
+ fprintf(stderr,"Datafile: %s\n",
+ datafile?datafile:"(null)");
+ fprintf(stderr,"Driverfile: %s\n",
+ driverfile?driverfile:"(null)");
+ fprintf(stderr,"Helpfile: %s\n",
+ helpfile?helpfile:"(null)");
+ fprintf(stderr,"LanguageMonitor: %s\n",
+ languagemonitor?languagemonitor:"(null)");
+ fprintf(stderr,"VendorSetup: %s\n",
+ vendorsetup?vendorsetup:"(null)");
+ if (copyfiles) scan_copyfiles(fichier,copyfiles);
+}
+
+int main(int argc, char *argv[])
+{
+ char *short_desc;
+ FILE *inf_file;
+
+ if (argc!=3)
+ {
+ usage(argv[0]);
+ return(-1);
+ }
+
+ inf_file=sys_fopen(argv[1],"r");
+ if (!inf_file)
+ {
+ fprintf(stderr,"Description file not found, bye\n");
+ return(-1);
+ }
+
+ lookup_strings(inf_file);
+
+ short_desc=find_desc(inf_file,argv[2]);
+ if (short_desc==NULL)
+ {
+ fprintf(stderr,"Printer not found\n");
+ return(-1);
+ }
+ else fprintf(stderr,"Found:%s\n",short_desc);
+
+ lookup_entry(inf_file,"DestinationDirs");
+ build_subdir();
+
+ if((files_to_copy=(char *)malloc(2048*sizeof(char))) == NULL) {
+ fprintf(stderr, "%s: malloc fail.\n", argv[0] );
+ exit(1);
+ }
+ *files_to_copy='\0';
+ scan_short_desc(inf_file,short_desc);
+ fprintf(stdout,"%s:%s:%s:",
+ argv[2],driverfile,datafile);
+ fprintf(stdout,"%s:",
+ helpfile?helpfile:"");
+ fprintf(stdout,"%s:",
+ languagemonitor?languagemonitor:"");
+ fprintf(stdout,"%s:",datatype);
+ fprintf(stdout,"%s\n",files_to_copy);
+ return 0;
+}
+
diff --git a/source3/utils/net.c b/source3/utils/net.c
new file mode 100644
index 0000000000..b81e37c0af
--- /dev/null
+++ b/source3/utils/net.c
@@ -0,0 +1,458 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
+ Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+
+ Originally written by Steve and Jim. Largely rewritten by tridge in
+ November 2001.
+
+ Reworked again by abartlet in December 2001
+
+ 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. */
+
+/*****************************************************/
+/* */
+/* Distributed SMB/CIFS Server Management Utility */
+/* */
+/* The intent was to make the syntax similar */
+/* to the NET utility (first developed in DOS */
+/* with additional interesting & useful functions */
+/* added in later SMB server network operating */
+/* systems). */
+/* */
+/*****************************************************/
+
+#include "includes.h"
+#include "../utils/net.h"
+
+/***********************************************************************/
+/* Beginning of internationalization section. Translatable constants */
+/* should be kept in this area and referenced in the rest of the code. */
+/* */
+/* No functions, outside of Samba or LSB (Linux Standards Base) should */
+/* be used (if possible). */
+/***********************************************************************/
+
+#define YES_STRING "Yes"
+#define NO_STRING "No"
+
+/************************************************************************************/
+/* end of internationalization section */
+/************************************************************************************/
+
+/* Yes, these buggers are globals.... */
+char *opt_requester_name = NULL;
+char *opt_host = NULL;
+char *opt_password = NULL;
+char *opt_user_name = NULL;
+BOOL opt_user_specified = False;
+char *opt_workgroup = NULL;
+int opt_long_list_entries = 0;
+int opt_reboot = 0;
+int opt_force = 0;
+int opt_port = 0;
+int opt_maxusers = -1;
+char *opt_comment = "";
+int opt_flags = -1;
+int opt_jobid = 0;
+int opt_timeout = 0;
+char *opt_target_workgroup = NULL;
+
+BOOL opt_have_ip = False;
+struct in_addr opt_dest_ip;
+
+extern pstring global_myname;
+
+/*
+ run a function from a function table. If not found then
+ call the specified usage function
+*/
+int net_run_function(int argc, const char **argv, struct functable *table,
+ int (*usage_fn)(int argc, const char **argv))
+{
+ int i;
+
+ if (argc < 1) {
+ d_printf("\nUsage: \n");
+ return usage_fn(argc, argv);
+ }
+ for (i=0; table[i].funcname; i++) {
+ if (StrCaseCmp(argv[0], table[i].funcname) == 0)
+ return table[i].fn(argc-1, argv+1);
+ }
+ d_printf("No command: %s\n", argv[0]);
+ return usage_fn(argc, argv);
+}
+
+
+/****************************************************************************
+connect to \\server\ipc$
+****************************************************************************/
+NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
+ const char *server_name)
+{
+ NTSTATUS nt_status;
+
+ if (!opt_password) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ opt_password = strdup(pass);
+ }
+ }
+
+ nt_status = cli_full_connection(c, opt_requester_name, server_name,
+ server_ip, opt_port,
+ "IPC$", "IPC",
+ opt_user_name, opt_workgroup,
+ opt_password, strlen(opt_password));
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ } else {
+ DEBUG(1,("Cannot connect to server. Error was %s\n",
+ nt_errstr(nt_status)));
+
+ /* Display a nicer message depending on the result */
+
+ if (NT_STATUS_V(nt_status) ==
+ NT_STATUS_V(NT_STATUS_LOGON_FAILURE))
+ d_printf("The username or password was not correct.\n");
+
+ return nt_status;
+ }
+}
+
+/****************************************************************************
+connect to \\server\ipc$ anonymously
+****************************************************************************/
+NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
+ struct in_addr *server_ip, const char *server_name)
+{
+ NTSTATUS nt_status;
+
+ nt_status = cli_full_connection(c, opt_requester_name, server_name,
+ server_ip, opt_port,
+ "IPC$", "IPC",
+ "", "",
+ "", 0);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ } else {
+ DEBUG(1,("Cannot connect to server (anonymously). Error was %s\n", nt_errstr(nt_status)));
+ return nt_status;
+ }
+}
+
+BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name)
+{
+
+ if (opt_host) {
+ *server_name = strdup(opt_host);
+ }
+
+ if (opt_have_ip) {
+ *server_ip = opt_dest_ip;
+ if (!*server_name) {
+ *server_name = strdup(inet_ntoa(opt_dest_ip));
+ }
+ } else if (*server_name) {
+ /* resolve the IP address */
+ if (!resolve_name(*server_name, server_ip, 0x20)) {
+ DEBUG(1,("Unable to resolve server name\n"));
+ return False;
+ }
+ } else if (flags & NET_FLAGS_PDC) {
+ struct in_addr *ip_list;
+ int addr_count;
+ if (get_dc_list(True /* PDC only*/, opt_target_workgroup, &ip_list, &addr_count)) {
+ fstring dc_name;
+ if (addr_count < 1) {
+ return False;
+ }
+
+ *server_ip = *ip_list;
+
+ if (is_zero_ip(*server_ip))
+ return False;
+
+ if (!lookup_dc_name(global_myname, opt_target_workgroup, server_ip, dc_name))
+ return False;
+
+ *server_name = strdup(dc_name);
+ }
+
+ } else if (flags & NET_FLAGS_DMB) {
+ struct in_addr msbrow_ip;
+ /* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
+ if (!resolve_name(opt_target_workgroup, &msbrow_ip, 0x1B)) {
+ DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
+ return False;
+ } else {
+ *server_ip = msbrow_ip;
+ }
+ *server_name = strdup(inet_ntoa(opt_dest_ip));
+ } else if (flags & NET_FLAGS_MASTER) {
+ struct in_addr brow_ips;
+ if (!resolve_name(opt_target_workgroup, &brow_ips, 0x1D)) {
+ /* go looking for workgroups */
+ DEBUG(1,("Unable to resolve master browser via name lookup\n"));
+ return False;
+ } else {
+ *server_ip = brow_ips;
+ }
+ *server_name = strdup(inet_ntoa(opt_dest_ip));
+ } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) {
+ extern struct in_addr loopback_ip;
+ *server_ip = loopback_ip;
+ *server_name = strdup("127.0.0.1");
+ }
+
+ if (!server_name || !*server_name) {
+ DEBUG(1,("no server to connect to\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, char *domain_name)
+{
+ struct in_addr *ip_list;
+ int addr_count;
+
+ if (get_dc_list(True /* PDC only*/, domain_name, &ip_list, &addr_count)) {
+ fstring dc_name;
+ if (addr_count < 1) {
+ return False;
+ }
+
+ *server_ip = *ip_list;
+
+ if (is_zero_ip(*server_ip))
+ return False;
+
+ if (!lookup_dc_name(global_myname, domain_name, server_ip, dc_name))
+ return False;
+
+ safe_strcpy(server_name, dc_name, FSTRING_LEN);
+ return True;
+ } else
+ return False;
+}
+
+
+struct cli_state *net_make_ipc_connection(unsigned flags)
+{
+ char *server_name = NULL;
+ struct in_addr server_ip;
+ struct cli_state *cli = NULL;
+ NTSTATUS nt_status;
+
+ if (!net_find_server(flags, &server_ip, &server_name)) {
+ d_printf("\nUnable to find a suitable server\n");
+ return NULL;
+ }
+
+ if (flags & NET_FLAGS_ANONYMOUS) {
+ nt_status = connect_to_ipc_anonymous(&cli, &server_ip, server_name);
+ } else {
+ nt_status = connect_to_ipc(&cli, &server_ip, server_name);
+ }
+ SAFE_FREE(server_name);
+ return cli;
+}
+
+
+
+static int net_user(int argc, const char **argv)
+{
+ if (net_ads_check() == 0)
+ return net_ads_user(argc, argv);
+
+ /* if server is not specified, default to PDC? */
+ if (net_rpc_check(NET_FLAGS_PDC))
+ return net_rpc_user(argc, argv);
+
+ return net_rap_user(argc, argv);
+}
+
+
+static int net_join(int argc, const char **argv)
+{
+ if (net_ads_check() == 0) {
+ if (net_ads_join(argc, argv) == 0)
+ return 0;
+ else
+ d_printf("ADS join did not work, trying RPC...\n");
+ }
+ return net_rpc_join(argc, argv);
+}
+
+/* main function table */
+static struct functable net_func[] = {
+ {"RPC", net_rpc},
+ {"RAP", net_rap},
+ {"ADS", net_ads},
+
+ /* eventually these should auto-choose the transport ... */
+ {"FILE", net_rap_file},
+ {"SHARE", net_rap_share},
+ {"SESSION", net_rap_session},
+ {"SERVER", net_rap_server},
+ {"DOMAIN", net_rap_domain},
+ {"PRINTQ", net_rap_printq},
+ {"USER", net_user},
+ {"GROUP", net_rap_group},
+ {"VALIDATE", net_rap_validate},
+ {"GROUPMEMBER", net_rap_groupmember},
+ {"ADMIN", net_rap_admin},
+ {"SERVICE", net_rap_service},
+ {"PASSWORD", net_rap_password},
+ {"TIME", net_time},
+ {"LOOKUP", net_lookup},
+ {"JOIN", net_join},
+
+ {"HELP", net_help},
+ {NULL, NULL}
+};
+
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc, const char **argv)
+{
+ int opt,i;
+ char *p;
+ int rc = 0;
+ int argc_new = 0;
+ const char ** argv_new;
+ poptContext pc;
+ static char *servicesf = dyn_CONFIGFILE;
+ static int debuglevel = 0;
+
+ struct poptOption long_options[] = {
+ {"help", 'h', POPT_ARG_NONE, 0, 'h'},
+ {"workgroup", 'w', POPT_ARG_STRING, &opt_target_workgroup},
+ {"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup},
+ {"user", 'U', POPT_ARG_STRING, &opt_user_name, 'U'},
+ {"ipaddress", 'I', POPT_ARG_STRING, 0,'I'},
+ {"port", 'p', POPT_ARG_INT, &opt_port},
+ {"myname", 'n', POPT_ARG_STRING, &opt_requester_name},
+ {"conf", 's', POPT_ARG_STRING, &servicesf},
+ {"debug", 'd', POPT_ARG_INT, &debuglevel},
+ {"debuglevel", 'd', POPT_ARG_INT, &debuglevel},
+ {"server", 'S', POPT_ARG_STRING, &opt_host},
+ {"comment", 'C', POPT_ARG_STRING, &opt_comment},
+ {"maxusers", 'M', POPT_ARG_INT, &opt_maxusers},
+ {"flags", 'F', POPT_ARG_INT, &opt_flags},
+ {"jobid", 'j', POPT_ARG_INT, &opt_jobid},
+ {"long", 'l', POPT_ARG_NONE, &opt_long_list_entries},
+ {"reboot", 'r', POPT_ARG_NONE, &opt_reboot},
+ {"force", 'f', POPT_ARG_NONE, &opt_force},
+ {"timeout", 't', POPT_ARG_INT, &opt_timeout},
+ { 0, 0, 0, 0}
+ };
+
+ zero_ip(&opt_dest_ip);
+
+ dbf = x_stderr;
+
+ pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'h':
+ net_help(argc, argv);
+ exit(0);
+ break;
+ case 'I':
+ opt_dest_ip = *interpret_addr2(poptGetOptArg(pc));
+ if (is_zero_ip(opt_dest_ip))
+ d_printf("\nInvalid ip address specified\n");
+ else
+ opt_have_ip = True;
+ break;
+ case 'U':
+ opt_user_specified = True;
+ opt_user_name = strdup(opt_user_name);
+ p = strchr(opt_user_name,'%');
+ if (p) {
+ *p = 0;
+ opt_password = p+1;
+ }
+ break;
+ default:
+ d_printf("\nInvalid option %c (%d)\n", (char)opt, opt);
+ net_help(argc, argv);
+ }
+ }
+
+ lp_load(servicesf,True,False,False);
+
+ DEBUGLEVEL = debuglevel;
+
+ argv_new = (const char **)poptGetArgs(pc);
+
+ argc_new = argc;
+ for (i=0; i<argc; i++) {
+ if (argv_new[i] == NULL) {
+ argc_new = i;
+ break;
+ }
+ }
+
+ if (!opt_requester_name) {
+ static fstring myname;
+ get_myname(myname);
+ opt_requester_name = myname;
+ }
+
+ if (!opt_user_name && getenv("LOGNAME")) {
+ opt_user_name = getenv("LOGNAME");
+ }
+
+ if (!opt_workgroup) {
+ opt_workgroup = lp_workgroup();
+ }
+
+ if (!opt_target_workgroup) {
+ opt_target_workgroup = lp_workgroup();
+ }
+
+ if (!*global_myname) {
+ char *p2;
+
+ fstrcpy(global_myname, myhostname());
+ p2 = strchr_m(global_myname, '.');
+ if (p2)
+ *p2 = 0;
+ }
+
+ strupper(global_myname);
+
+ load_interfaces();
+
+ rc = net_run_function(argc_new-1, argv_new+1, net_func, net_help);
+
+ DEBUG(2,("return code = %d\n", rc));
+ return rc;
+}
diff --git a/source3/utils/net.h b/source3/utils/net.h
new file mode 100644
index 0000000000..af6f153f7b
--- /dev/null
+++ b/source3/utils/net.h
@@ -0,0 +1,51 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+
+ 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. */
+
+#define NET_FLAGS_MASTER 1
+#define NET_FLAGS_DMB 2
+
+/* Would it be insane to set 'localhost' as the default
+ remote host for this operation?
+
+ For example, localhost is insane for a 'join' operation.
+*/
+#define NET_FLAGS_LOCALHOST_DEFAULT_INSANE 4
+
+/* We want to find the PDC only */
+#define NET_FLAGS_PDC 8
+
+/* We want an anonymous connection */
+#define NET_FLAGS_ANONYMOUS 16
+
+
+extern int opt_maxusers;
+extern char *opt_comment;
+extern int opt_flags;
+
+extern char *opt_comment;
+
+extern char *opt_target_workgroup;
+extern int opt_long_list_entries;
+extern int opt_reboot;
+extern int opt_force;
+extern int opt_timeout;
+extern char *opt_host;
+extern char *opt_user_name;
+extern char *opt_password;
+extern BOOL opt_user_specified;
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
new file mode 100644
index 0000000000..68fa89ea35
--- /dev/null
+++ b/source3/utils/net_ads.c
@@ -0,0 +1,787 @@
+/*
+ Samba Unix/Linux SMB client library
+ net ads commands
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+ Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
+ Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+
+ 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 "../utils/net.h"
+
+#ifdef HAVE_ADS
+
+int net_ads_usage(int argc, const char **argv)
+{
+ d_printf(
+"\nnet ads join <org_unit>"\
+"\n\tjoins the local machine to a ADS realm\n"\
+"\nnet ads leave"\
+"\n\tremoves the local machine from a ADS realm\n"\
+"\nnet ads user"\
+"\n\tlist users in the realm\n"\
+"\nnet ads group"\
+"\n\tlist groups in the realm\n"\
+"\nnet ads info"\
+"\n\tshows some info on the server\n"\
+"\nnet ads status"\
+"\n\tdump the machine account details to stdout\n"
+"\nnet ads password <username@realm> -Uadmin_username@realm%%admin_pass"\
+"\n\tchange a user's password using an admin account"
+"\n\t(note: use realm in UPPERCASE)\n"
+"\nnet ads chostpass"
+"\n\tchange the trust account password of this machine in the AD tree\n"
+"\nnet ads printer [info | publish | remove] <printername> <servername>"
+"\n\t lookup, add, or remove directory entry for a printer\n"
+ );
+ return -1;
+}
+
+
+static int net_ads_info(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+
+ ads = ads_init(NULL, opt_host, NULL, NULL);
+ ads_connect(ads);
+
+ if (!ads) {
+ d_printf("Didn't find the ldap server!\n");
+ return -1;
+ }
+
+ d_printf("LDAP server: %s\n", ads->ldap_server);
+ d_printf("LDAP server name: %s\n", ads->ldap_server_name);
+ d_printf("Realm: %s\n", ads->realm);
+ d_printf("Bind Path: %s\n", ads->bind_path);
+ d_printf("LDAP port: %d\n", ads->ldap_port);
+
+ return 0;
+}
+
+
+static ADS_STRUCT *ads_startup(void)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ BOOL need_password = False;
+ BOOL second_time = False;
+
+ ads = ads_init(NULL, opt_host, NULL, NULL);
+
+ if (!opt_user_name) {
+ opt_user_name = "administrator";
+ }
+
+ if (opt_user_specified)
+ need_password = True;
+
+retry:
+ if (!opt_password && need_password) {
+ char *prompt;
+ asprintf(&prompt,"%s password: ", opt_user_name);
+ opt_password = getpass(prompt);
+ free(prompt);
+ }
+
+ if (opt_password)
+ ads->password = strdup(opt_password);
+
+ ads->user_name = strdup(opt_user_name);
+
+ status = ads_connect(ads);
+ if (!ADS_ERR_OK(status)) {
+ if (!need_password && !second_time) {
+ need_password = True;
+ second_time = True;
+ goto retry;
+ } else {
+ DEBUG(1,("ads_connect: %s\n", ads_errstr(status)));
+ return NULL;
+ }
+ }
+ return ads;
+}
+
+
+/*
+ Check to see if connection can be made via ads.
+ ads_startup() stores the password in opt_password if it needs to so
+ that rpc or rap can use it without re-prompting.
+*/
+int net_ads_check(void)
+{
+ ADS_STRUCT *ads;
+
+ ads = ads_startup();
+ if (!ads)
+ return -1;
+ ads_destroy(&ads);
+ return 0;
+}
+
+
+static void usergrp_display(char *field, void **values, void *data_area)
+{
+ char **disp_fields = (char **) data_area;
+
+ if (!field) { /* must be end of record */
+ if (!strchr_m(disp_fields[0], '$')) {
+ if (disp_fields[1])
+ printf("%-21.21s %-50.50s\n",
+ disp_fields[0], disp_fields[1]);
+ else
+ printf("%-21.21s\n", disp_fields[0]);
+ }
+ SAFE_FREE(disp_fields[0]);
+ SAFE_FREE(disp_fields[1]);
+ return;
+ }
+ if (StrCaseCmp(field, "sAMAccountName") == 0) {
+ disp_fields[0] = strdup(((struct berval *) values[0])->bv_val);
+ }
+ if (StrCaseCmp(field, "description") == 0)
+ disp_fields[1] = strdup(((struct berval *) values[0])->bv_val);
+}
+
+static int net_ads_user_usage(int argc, const char **argv)
+{
+ return net_help_user(argc, argv);
+}
+
+static int ads_user_add(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ void *res=NULL;
+ int rc = -1;
+
+ if (argc < 1) return net_ads_user_usage(argc, argv);
+
+ if (!(ads = ads_startup())) return -1;
+
+ status = ads_find_user_acct(ads, &res, argv[0]);
+
+ if (!ADS_ERR_OK(status)) {
+ d_printf("ads_user_add: %s\n", ads_errstr(status));
+ goto done;
+ }
+
+ if (ads_count_replies(ads, res)) {
+ d_printf("ads_user_add: User %s already exists\n", argv[0]);
+ ads_msgfree(ads, res);
+ goto done;
+ }
+
+ status = ads_add_user_acct(ads, argv[0], opt_comment);
+
+ if (ADS_ERR_OK(status)) {
+ d_printf("User %s added\n", argv[0]);
+ rc = 0;
+ } else {
+ d_printf("Could not add user %s: %s\n", argv[0],
+ ads_errstr(status));
+ }
+
+ done:
+ if (res)
+ ads_msgfree(ads, res);
+ ads_destroy(&ads);
+ return rc;
+}
+
+static int ads_user_info(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ void *res;
+ const char *attrs[] = {"memberOf", NULL};
+ char *searchstring=NULL;
+ char **grouplist;
+
+ if (argc < 1) return net_ads_user_usage(argc, argv);
+
+ if (!(ads = ads_startup())) return -1;
+
+ asprintf(&searchstring, "(sAMAccountName=%s)", argv[0]);
+ rc = ads_search(ads, &res, searchstring, attrs);
+ safe_free(searchstring);
+
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_search: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ grouplist = ldap_get_values(ads->ld, res, "memberOf");
+
+ if (grouplist) {
+ int i;
+ char **groupname;
+ for (i=0;grouplist[i];i++) {
+ groupname = ldap_explode_dn(grouplist[i], 1);
+ printf("%s\n", groupname[0]);
+ ldap_value_free(groupname);
+ }
+ ldap_value_free(grouplist);
+ }
+
+ ads_msgfree(ads, res);
+
+ ads_destroy(&ads);
+ return 0;
+}
+
+static int ads_user_delete(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ void *res;
+ char *userdn;
+
+ if (argc < 1) return net_ads_user_usage(argc, argv);
+
+ if (!(ads = ads_startup())) return -1;
+
+ rc = ads_find_user_acct(ads, &res, argv[0]);
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(0, ("User %s does not exist\n", argv[0]));
+ return -1;
+ }
+ userdn = ads_get_dn(ads, res);
+ ads_msgfree(ads, res);
+ rc = ads_del_dn(ads, userdn);
+ ads_memfree(ads, userdn);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("User %s deleted\n", argv[0]);
+ return 0;
+ }
+ d_printf("Error deleting user %s: %s\n", argv[0],
+ ads_errstr(rc));
+ return -1;
+}
+
+int net_ads_user(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"ADD", ads_user_add},
+ {"INFO", ads_user_info},
+ {"DELETE", ads_user_delete},
+ {NULL, NULL}
+ };
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ const char *shortattrs[] = {"sAMAccountName", NULL};
+ const char *longattrs[] = {"sAMAccountName", "description", NULL};
+ char *disp_fields[2] = {NULL, NULL};
+
+ if (argc == 0) {
+ if (!(ads = ads_startup())) return -1;
+
+ if (opt_long_list_entries)
+ d_printf("\nUser name Comment"\
+ "\n-----------------------------\n");
+
+ rc = ads_do_search_all_fn(ads, ads->bind_path,
+ LDAP_SCOPE_SUBTREE,
+ "(objectclass=user)",
+ opt_long_list_entries ? longattrs :
+ shortattrs, usergrp_display,
+ disp_fields);
+ ads_destroy(&ads);
+ return 0;
+ }
+
+ return net_run_function(argc, argv, func, net_ads_user_usage);
+}
+
+static int net_ads_group(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ const char *shortattrs[] = {"sAMAccountName", NULL};
+ const char *longattrs[] = {"sAMAccountName", "description", NULL};
+ char *disp_fields[2] = {NULL, NULL};
+
+ if (!(ads = ads_startup())) return -1;
+
+ if (opt_long_list_entries)
+ d_printf("\nGroup name Comment"\
+ "\n-----------------------------\n");
+ rc = ads_do_search_all_fn(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ "(objectclass=group)", opt_long_list_entries
+ ? longattrs : shortattrs, usergrp_display,
+ disp_fields);
+
+ ads_destroy(&ads);
+ return 0;
+}
+
+static int net_ads_status(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ extern pstring global_myname;
+ void *res;
+
+ if (!(ads = ads_startup())) return -1;
+
+ rc = ads_find_machine_acct(ads, &res, global_myname);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ if (ads_count_replies(ads, res) == 0) {
+ d_printf("No machine account for '%s' found\n", global_myname);
+ return -1;
+ }
+
+ ads_dump(ads, res);
+
+ return 0;
+}
+
+static int net_ads_leave(int argc, const char **argv)
+{
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS rc;
+ extern pstring global_myname;
+
+ if (!secrets_init()) {
+ DEBUG(1,("Failed to initialise secrets database\n"));
+ return -1;
+ }
+
+ if (!opt_password) {
+ asprintf(&opt_user_name, "%s$", global_myname);
+ opt_password = secrets_fetch_machine_password();
+ }
+
+ if (!(ads = ads_startup())) {
+ return -1;
+ }
+
+ rc = ads_leave_realm(ads, global_myname);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("Failed to delete host '%s' from the '%s' realm.\n",
+ global_myname, ads->realm);
+ return -1;
+ }
+
+ d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->realm);
+
+ return 0;
+}
+
+int net_ads_join(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ char *password;
+ char *tmp_password;
+ extern pstring global_myname;
+ const char *org_unit = "Computers";
+ char *dn;
+ void *res;
+ DOM_SID dom_sid;
+ char *ou_str;
+
+ if (argc > 0) org_unit = argv[0];
+
+ if (!secrets_init()) {
+ DEBUG(1,("Failed to initialise secrets database\n"));
+ return -1;
+ }
+
+ tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ password = strdup(tmp_password);
+
+ if (!(ads = ads_startup())) return -1;
+
+ ou_str = ads_ou_string(org_unit);
+ asprintf(&dn, "%s,%s", ou_str, ads->bind_path);
+ free(ou_str);
+
+ rc = ads_search_dn(ads, &res, dn, NULL);
+ ads_msgfree(ads, res);
+
+ if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
+ d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
+ org_unit, dn);
+ return -1;
+ }
+ free(dn);
+
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ rc = ads_join_realm(ads, global_myname, org_unit);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ rc = ads_set_machine_password(ads, global_myname, password);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ rc = ads_domain_sid(ads, &dom_sid);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
+ DEBUG(1,("Failed to save domain sid\n"));
+ return -1;
+ }
+
+ if (!secrets_store_machine_password(password)) {
+ DEBUG(1,("Failed to save machine password\n"));
+ return -1;
+ }
+
+ d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->realm);
+
+ free(password);
+
+ return 0;
+}
+
+int net_ads_printer_usage(int argc, const char **argv)
+{
+ d_printf(
+"\nnet ads printer info <printer> <server>"
+"\n\tlookup info in directory for printer on server"
+"\n\t(note: printer defaults to \"*\", server defaults to local)\n"
+"\nnet ads printer publish <printername>"
+"\n\tpublish printer in directory"
+"\n\t(note: printer name is required)\n"
+"\nnet ads printer remove <printername>"
+"\n\tremove printer from directory"
+"\n\t(note: printer name is required)\n");
+ return -1;
+}
+
+static int net_ads_printer_info(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ char *servername, *printername;
+ extern pstring global_myname;
+ void *res = NULL;
+
+ if (!(ads = ads_startup())) return -1;
+
+ if (argc > 0)
+ printername = argv[0];
+ else
+ printername = "*";
+
+ if (argc > 1)
+ servername = argv[1];
+ else
+ servername = global_myname;
+
+ rc = ads_find_printer_on_server(ads, &res, printername, servername);
+
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
+ ads_msgfree(ads, res);
+ return -1;
+ }
+
+ if (ads_count_replies(ads, res) == 0) {
+ d_printf("Printer '%s' not found\n", printername);
+ ads_msgfree(ads, res);
+ return -1;
+ }
+
+ ads_dump(ads, res);
+ ads_msgfree(ads, res);
+
+ return 0;
+}
+
+static int net_ads_printer_publish(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ char *uncname, *servername;
+ ADS_PRINTER_ENTRY prt;
+ extern pstring global_myname;
+
+ /*
+ these const strings are only here as an example. The attributes
+ they represent are not implemented yet
+ */
+ const char *bins[] = {"Tray 21", NULL};
+ const char *media[] = {"Letter", NULL};
+ const char *orients[] = {"PORTRAIT", NULL};
+ const char *ports[] = {"Samba", NULL};
+
+ if (!(ads = ads_startup())) return -1;
+
+ if (argc < 1)
+ return net_ads_printer_usage(argc, argv);
+
+ memset(&prt, 0, sizeof(ADS_PRINTER_ENTRY));
+
+ prt.printerName = argv[0];
+ asprintf(&servername, "%s.%s", global_myname, ads->realm);
+ prt.serverName = servername;
+ prt.shortServerName = global_myname;
+ prt.versionNumber = "4";
+ asprintf(&uncname, "\\\\%s\\%s", global_myname, argv[0]);
+ prt.uNCName=uncname;
+ prt.printBinNames = (char **) bins;
+ prt.printMediaSupported = (char **) media;
+ prt.printOrientationsSupported = (char **) orients;
+ prt.portName = (char **) ports;
+ prt.printSpooling = "PrintAfterSpooled";
+
+ rc = ads_add_printer(ads, &prt);
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ d_printf("published printer\n");
+
+ return 0;
+}
+
+static int net_ads_printer_remove(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ char *servername, *prt_dn;
+ extern pstring global_myname;
+ void *res = NULL;
+
+ if (!(ads = ads_startup())) return -1;
+
+ if (argc < 1)
+ return net_ads_printer_usage(argc, argv);
+
+ if (argc > 1)
+ servername = argv[1];
+ else
+ servername = global_myname;
+
+ rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
+
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
+ ads_msgfree(ads, res);
+ return -1;
+ }
+
+ if (ads_count_replies(ads, res) == 0) {
+ d_printf("Printer '%s' not found\n", argv[1]);
+ ads_msgfree(ads, res);
+ return -1;
+ }
+
+ prt_dn = ads_get_dn(ads, res);
+ ads_msgfree(ads, res);
+ rc = ads_del_dn(ads, prt_dn);
+ ads_memfree(ads, prt_dn);
+
+ if (!ADS_ERR_OK(rc)) {
+ d_printf("ads_del_dn: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int net_ads_printer(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"INFO", net_ads_printer_info},
+ {"PUBLISH", net_ads_printer_publish},
+ {"REMOVE", net_ads_printer_remove},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_printer_usage);
+}
+
+
+static int net_ads_password(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ char *auth_principal = opt_user_name;
+ char *auth_password = opt_password;
+ char *realm = NULL;
+ char *new_password = NULL;
+ char *c;
+ char *prompt;
+ ADS_STATUS ret;
+
+
+ if ((argc != 1) || (opt_user_name == NULL) ||
+ (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
+ (strchr(argv[0], '@') == NULL)) {
+ return net_ads_usage(argc, argv);
+ }
+
+ c = strchr(auth_principal, '@');
+ realm = ++c;
+
+ /* use the realm so we can eventually change passwords for users
+ in realms other than default */
+ if (!(ads = ads_init(realm, NULL, NULL, NULL))) return -1;
+
+ asprintf(&prompt, "Enter new password for %s:", argv[0]);
+
+ new_password = getpass(prompt);
+
+ ret = kerberos_set_password(ads->kdc_server, auth_principal,
+ auth_password, argv[0], new_password);
+ if (!ADS_ERR_OK(ret)) {
+ d_printf("Password change failed :-( ...\n");
+ ads_destroy(&ads);
+ free(prompt);
+ return -1;
+ }
+
+ d_printf("Password change for %s completed.\n", argv[0]);
+ ads_destroy(&ads);
+ free(prompt);
+
+ return 0;
+}
+
+
+static int net_ads_change_localhost_pass(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ extern pstring global_myname;
+ char *host_principal;
+ char *hostname;
+ ADS_STATUS ret;
+
+
+ if (!(ads = ads_init(NULL, NULL, NULL, NULL))) return -1;
+
+ hostname = strdup(global_myname);
+ strlower(hostname);
+ asprintf(&host_principal, "%s@%s", hostname, ads->realm);
+ SAFE_FREE(hostname);
+ d_printf("Changing password for principal: HOST/%s\n", host_principal);
+
+ ret = ads_change_trust_account_password(ads, host_principal);
+
+ if (!ADS_ERR_OK(ret)) {
+ d_printf("Password change failed :-( ...\n");
+ ads_destroy(&ads);
+ SAFE_FREE(host_principal);
+ return -1;
+ }
+
+ d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
+ ads_destroy(&ads);
+ SAFE_FREE(host_principal);
+
+ return 0;
+}
+
+int net_ads_help(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"USER", net_ads_user_usage},
+#if 0
+ {"INFO", net_ads_info},
+ {"JOIN", net_ads_join},
+ {"LEAVE", net_ads_leave},
+ {"STATUS", net_ads_status},
+ {"GROUP", net_ads_group},
+ {"PASSWORD", net_ads_password},
+ {"CHOSTPASS", net_ads_change_localhost_pass},
+ {"PRINTER", net_ads_printer},
+#endif
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_usage);
+}
+
+int net_ads(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"INFO", net_ads_info},
+ {"JOIN", net_ads_join},
+ {"LEAVE", net_ads_leave},
+ {"STATUS", net_ads_status},
+ {"USER", net_ads_user},
+ {"GROUP", net_ads_group},
+ {"PASSWORD", net_ads_password},
+ {"CHOSTPASS", net_ads_change_localhost_pass},
+ {"PRINTER", net_ads_printer},
+ {"HELP", net_ads_help},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_usage);
+}
+
+#else
+
+static int net_ads_noads(void)
+{
+ d_printf("ADS support not compiled in\n");
+ return -1;
+}
+
+int net_ads_usage(int argc, const char **argv)
+{
+ return net_ads_noads();
+}
+
+int net_ads_help(int argc, const char **argv)
+{
+ return net_ads_noads();
+}
+
+int net_ads_join(int argc, const char **argv)
+{
+ return net_ads_noads();
+}
+
+int net_ads_user(int argc, const char **argv)
+{
+ return net_ads_noads();
+}
+
+/* this one shouldn't display a message */
+int net_ads_check(void)
+{
+ return -1;
+}
+
+int net_ads(int argc, const char **argv)
+{
+ return net_ads_usage(argc, argv);
+}
+
+#endif
diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c
new file mode 100644
index 0000000000..21af8a4fd9
--- /dev/null
+++ b/source3/utils/net_help.c
@@ -0,0 +1,126 @@
+/*
+ Samba Unix/Linux SMB client library
+ net help commands
+ Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+
+ 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"
+
+int net_common_methods_usage(int argc, const char**argv)
+{
+ d_printf("Valid methods: (auto-detected if not specified)\n");
+ d_printf("\tads\t\t\t\tActive Directory (LDAP/Kerberos)\n");
+ d_printf("\trpc\t\t\t\tDCE-RPC\n");
+ d_printf("\trap\t\t\t\tRAP (older systems)\n");
+ d_printf("\n");
+ return 0;
+}
+
+int net_common_flags_usage(int argc, const char **argv)
+{
+ d_printf("Valid targets: choose one (none defaults to localhost)\n");
+ d_printf("\t-S or --server=<server>\t\tserver name\n");
+ d_printf("\t-I or --ipaddress=<ipaddr>\taddress of target server\n");
+ d_printf("\t-w or --workgroup=<wg>\t\ttarget workgroup or domain\n");
+
+ d_printf("\n");
+ d_printf("Valid miscellaneous options are:\n"); /* misc options */
+ d_printf("\t-p or --port=<port>\t\tconnection port on target\n");
+ d_printf("\t-W or --myworkgroup=<wg>\tclient workgroup\n");
+ d_printf("\t-d or --debug=<level>\t\tdebug level (0-10)\n");
+ d_printf("\t-n or --myname=<name>\t\tclient name\n");
+ d_printf("\t-U or --user=<name>\t\tuser name\n");
+ d_printf("\t-s or --conf=<path>\t\tpathname of smb.conf file\n");
+ d_printf("\t-l or --long\t\t\tDisplay full information\n");
+ return -1;
+}
+
+static int help_usage(int argc, const char **argv)
+{
+ d_printf(
+"\n"\
+"Usage: net help <function>\n"\
+"\n"\
+"Valid functions are:\n"\
+" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\
+" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n");
+ return -1;
+}
+
+int net_help_user(int argc, const char **argv)
+{
+ d_printf("\nnet [method] user [misc. options] [targets]\n\tList users\n");
+ d_printf("\nnet [method] user DELETE <name> [misc. options] [targets]"\
+ "\n\tDelete specified user\n");
+ d_printf("\nnet [method] user INFO <name> [misc. options] [targets]"\
+ "\n\tList the domain groups of the specified user\n");
+ d_printf("\nnet [method] user ADD <name> [-F user flags] [misc. options]"\
+ " [targets]\n\tAdd specified user\n");
+
+ net_common_methods_usage(argc, argv);
+ net_common_flags_usage(argc, argv);
+ d_printf(
+ "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n");
+ return -1;
+}
+
+static int net_usage(int argc, const char **argv)
+{
+ d_printf(" net time\t\tto view or set time information\n"\
+ " net lookup\t\tto lookup host name or ip address\n"\
+ " net user\t\tto manage users\n"\
+ " net join\t\tto join a domain\n"\
+ "\n"\
+ " net ads [command]\tto run ADS commands\n"\
+ " net rap [command]\tto run RAP (pre-RPC) commands\n"\
+ " net rpc [command]\tto run RPC commands\n"\
+ "\n"\
+ "Type \"net help <option>\" to get more information on that option\n");
+ return -1;
+}
+
+/*
+ handle "net help *" subcommands
+*/
+int net_help(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"ADS", net_ads_help},
+ {"RAP", net_rap_help},
+ {"RPC", net_rpc_help},
+
+ {"FILE", net_rap_file_usage},
+ {"SHARE", net_rap_share_usage},
+ {"SESSION", net_rap_session_usage},
+ {"SERVER", net_rap_server_usage},
+ {"DOMAIN", net_rap_domain_usage},
+ {"PRINTQ", net_rap_printq_usage},
+ {"USER", net_help_user},
+ {"GROUP", net_rap_group_usage},
+ {"VALIDATE", net_rap_validate_usage},
+ {"GROUPMEMBER", net_rap_groupmember_usage},
+ {"ADMIN", net_rap_admin_usage},
+ {"SERVICE", net_rap_service_usage},
+ {"PASSWORD", net_rap_password_usage},
+ {"TIME", net_time_usage},
+ {"LOOKUP", net_lookup_usage},
+
+ {"HELP", help_usage},
+ {NULL, NULL}};
+
+ return net_run_function(argc, argv, func, net_usage);
+}
diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c
new file mode 100644
index 0000000000..0cc1ff579f
--- /dev/null
+++ b/source3/utils/net_lookup.c
@@ -0,0 +1,61 @@
+/*
+ Samba Unix/Linux SMB client library
+ net lookup command
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+
+ 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 "../utils/net.h"
+
+int net_lookup_usage(int argc, const char **argv)
+{
+ d_printf(
+" net lookup host HOSTNAME <type>\n\tgives IP for a hostname\n\n"\
+"\n");
+ return -1;
+}
+
+/* lookup a hostname giving an IP */
+static int net_lookup_host(int argc, const char **argv)
+{
+ struct in_addr ip;
+ int name_type = 0x20;
+
+ if (argc == 0) return net_lookup_usage(argc, argv);
+ if (argc > 1) name_type = strtol(argv[1], NULL, 0);
+
+ if (!resolve_name(argv[0], &ip, name_type)) {
+ /* we deliberately use DEBUG() here to send it to stderr
+ so scripts aren't mucked up */
+ DEBUG(0,("Didn't find %s#%02x\n", argv[0], name_type));
+ return -1;
+ }
+
+ d_printf("%s\n", inet_ntoa(ip));
+ return 0;
+}
+
+
+/* lookup hosts or IP addresses using internal samba lookup fns */
+int net_lookup(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"HOST", net_lookup_host},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_lookup_usage);
+}
diff --git a/source3/utils/net_rap.c b/source3/utils/net_rap.c
new file mode 100644
index 0000000000..a6b199fd88
--- /dev/null
+++ b/source3/utils/net_rap.c
@@ -0,0 +1,1084 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
+ Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+
+ Originally written by Steve and Jim. Largely rewritten by tridge in
+ November 2001.
+
+ 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 "../utils/net.h"
+
+/* The following messages were for error checking that is not properly
+ reported at the moment. Which should be reinstated? */
+#define ERRMSG_TARGET_WG_NOT_VALID "\nTarget workgroup option not valid "\
+ "except on net rap server command, ignored"
+#define ERRMSG_INVALID_HELP_OPTION "\nInvalid help option\n"
+
+#define ERRMSG_BOTH_SERVER_IPADDRESS "\nTarget server and IP address both "\
+ "specified. Do not set both at the same time. The target IP address was used\n"
+
+static const char *share_type[] = {
+ "Disk",
+ "Print",
+ "Dev",
+ "IPC"
+};
+
+static int errmsg_not_implemented(void)
+{
+ d_printf("\nNot implemented\n");
+ return 0;
+}
+
+int net_rap_file_usage(int argc, const char **argv)
+{
+ d_printf("net rap file [misc. options] [targets]\n"\
+ "\tlists all open files on file server\n\n");
+ d_printf("net rap file USER <username> [misc. options] [targets]\n"\
+ "\tlists all files opened by username on file server\n\n");
+ d_printf("net rap file CLOSE <id> [misc. options] [targets]\n"\
+ "\tcloses specified file on target server\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+/***************************************************************************
+ list info on an open file
+***************************************************************************/
+static void file_fn(const char * pPath, const char * pUser, uint16 perms,
+ uint16 locks, uint32 id)
+{
+ d_printf("\t%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
+ id, pUser, perms, locks, pPath);
+}
+
+static void one_file_fn(const char *pPath, const char *pUser, uint16 perms,
+ uint16 locks, uint32 id)
+{
+ d_printf("File ID %d\n"\
+ "User name %s\n"\
+ "Locks 0x%-4.2x\n"\
+ "Path %s\n"\
+ "Permissions 0x%x\n",
+ id, pUser, locks, pPath, perms);
+}
+
+
+static int rap_file_close(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc == 0) {
+ d_printf("\nMissing fileid of file to close\n\n");
+ return net_rap_file_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetFileClose(cli, atoi(argv[0]));
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_file_info(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc == 0)
+ return net_rap_file_usage(argc, argv);
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetFileGetInfo(cli, atoi(argv[0]), one_file_fn);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_file_user(int argc, const char **argv)
+{
+ if (argc == 0)
+ return net_rap_file_usage(argc, argv);
+
+ d_printf("net rap file user not implemented yet\n");
+ return -1;
+}
+
+int net_rap_file(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"CLOSE", rap_file_close},
+ {"USER", rap_file_user},
+ {"INFO", rap_file_info},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ /* list open files */
+ d_printf(
+ "\nEnumerating open files on remote server:\n\n"\
+ "\n\tFileId Opened by Perms Locks Path \n"\
+ "\t------ --------- ----- ----- ---- \n");
+ ret = cli_NetFileEnum(cli, NULL, NULL, file_fn);
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_file_usage);
+}
+
+int net_rap_share_usage(int argc, const char **argv)
+{
+ d_printf(
+ "\nnet [rap] share [misc. options] [targets] \n"\
+ "\tenumerates all exported resources (network shares) "\
+ "on target server\n");
+ d_printf(
+ "\nnet rap share ADD <name=serverpath> [misc. options] [targets]"\
+ "\n\tAdds a share from a server (makes the export active)\n");
+ d_printf(
+ "\nnet rap share DELETE <sharename> [misc. options] [targets]\n"\
+ "\tor"\
+ "\nnet rap share CLOSE <sharename> [misc. options] [targets]"\
+ "\n\tDeletes a share from a server (makes the export inactive)\n");
+ net_common_flags_usage(argc, argv);
+ d_printf(
+ "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n");
+ d_printf("\t-M or --maxusers=<num>\t\tmax users allowed for share\n");
+ return -1;
+}
+
+static void long_share_fn(const char *share_name, uint32 type,
+ const char *comment, void *state)
+{
+ d_printf("%-12.12s %-8.8s %-50.50s\n",
+ share_name, share_type[type], comment);
+}
+
+static void share_fn(const char *share_name, uint32 type,
+ const char *comment, void *state)
+{
+ d_printf("%-12.12s\n", share_name);
+}
+
+static int rap_share_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (argc == 0) {
+ d_printf("\n\nShare name not specified\n");
+ return net_rap_share_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetShareDelete(cli, argv[0]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_share_add(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ RAP_SHARE_INFO_2 sinfo;
+ char *p;
+ char *sharename;
+
+ if (argc == 0) {
+ d_printf("\n\nShare name not specified\n");
+ return net_rap_share_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ sharename = strdup(argv[0]);
+ p = strchr(sharename, '=');
+ *p = 0;
+ strlcpy(sinfo.share_name, sharename, sizeof(sinfo.share_name));
+ sinfo.reserved1 = '\0';
+ sinfo.share_type = 0;
+ sinfo.comment = opt_comment;
+ sinfo.perms = 0;
+ sinfo.maximum_users = opt_maxusers;
+ sinfo.active_users = 0;
+ sinfo.path = p+1;
+ memset(sinfo.password, '\0', sizeof(sinfo.password));
+ sinfo.reserved2 = '\0';
+
+ ret = cli_NetShareAdd(cli, &sinfo);
+ cli_shutdown(cli);
+ return ret;
+}
+
+
+int net_rap_share(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"DELETE", rap_share_delete},
+ {"CLOSE", rap_share_delete},
+ {"ADD", rap_share_add},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (opt_long_list_entries) {
+ d_printf(
+ "\nEnumerating shared resources (exports) on remote server:\n\n"\
+ "\nShare name Type Description\n"\
+ "---------- ---- -----------\n");
+ ret = cli_RNetShareEnum(cli, long_share_fn, NULL);
+ }
+ ret = cli_RNetShareEnum(cli, share_fn, NULL);
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_share_usage);
+}
+
+
+int net_rap_session_usage(int argc, const char **argv)
+{
+ d_printf(
+ "\nnet rap session [misc. options] [targets]"\
+ "\n\tenumerates all active SMB/CIFS sessions on target server\n");
+ d_printf(
+ "\nnet rap session DELETE <client_name> [misc. options] [targets] \n"\
+ "\tor"\
+ "\nnet rap session CLOSE <client_name> [misc. options] [targets]"\
+ "\n\tDeletes (closes) a session from specified client to server\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+static void list_sessions_func(char *wsname, char *username, uint16 conns,
+ uint16 opens, uint16 users, uint32 sess_time,
+ uint32 idle_time, uint32 user_flags, char *clitype)
+{
+ int hrs = idle_time / 3600;
+ int min = (idle_time / 60) % 60;
+ int sec = idle_time % 60;
+
+ d_printf("\\\\%-18.18s %-20.20s %-18.18s %5d %2.2d:%2.2d:%2.2d\n",
+ wsname, username, clitype, opens, hrs, min, sec);
+}
+
+static void display_session_func(const char *wsname, const char *username,
+ uint16 conns, uint16 opens, uint16 users,
+ uint32 sess_time, uint32 idle_time,
+ uint32 user_flags, const char *clitype)
+{
+ int ihrs = idle_time / 3600;
+ int imin = (idle_time / 60) % 60;
+ int isec = idle_time % 60;
+ int shrs = sess_time / 3600;
+ int smin = (sess_time / 60) % 60;
+ int ssec = sess_time % 60;
+ d_printf("User name %-20.20s\n"\
+ "Computer %-20.20s\n"\
+ "Guest logon %-20.20s\n"\
+ "Client Type %-40.40s\n"\
+ "Sess time %2.2d:%2.2d:%2.2d\n"\
+ "Idle time %2.2d:%2.2d:%2.2d\n",
+ username, wsname,
+ (user_flags&0x0)?"yes":"no", clitype,
+ shrs, smin, ssec, ihrs, imin, isec);
+}
+
+static void display_conns_func(uint16 conn_id, uint16 conn_type, uint16 opens,
+ uint16 users, uint32 conn_time,
+ const char *username, const char *netname)
+{
+ d_printf("%-14.14s %-8.8s %5d\n",
+ netname, share_type[conn_type], opens);
+}
+
+static int rap_session_info(int argc, const char **argv)
+{
+ const char *sessname;
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (argc == 0)
+ return net_rap_session_usage(argc, argv);
+
+ sessname = argv[0];
+
+ ret = cli_NetSessionGetInfo(cli, sessname, display_session_func);
+ if (ret < 0) {
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ d_printf("Share name Type # Opens\n-------------------------"\
+ "-----------------------------------------------------\n");
+ ret = cli_NetConnectionEnum(cli, sessname, display_conns_func);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_session_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (argc == 0)
+ return net_rap_session_usage(argc, argv);
+
+ ret = cli_NetSessionDel(cli, argv[0]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_session(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"INFO", rap_session_info},
+ {"DELETE", rap_session_delete},
+ {"CLOSE", rap_session_delete},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ d_printf("Computer User name "\
+ "Client Type Opens Idle time\n"\
+ "------------------------------------------"\
+ "------------------------------------\n");
+ ret = cli_NetSessionEnum(cli, list_sessions_func);
+
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_session_usage);
+}
+
+/****************************************************************************
+list a server name
+****************************************************************************/
+static void display_server_func(const char *name, uint32 m,
+ const char *comment, void * reserved)
+{
+ d_printf("\t%-16.16s %s\n", name, comment);
+}
+
+
+int net_rap_server_usage(int argc, const char **argv)
+{
+ d_printf("net rap server [misc. options] [target]\n\t"\
+ "lists the servers in the specified domain or workgroup.\n");
+ d_printf("\n\tIf domain is not specified, it uses the current"\
+ " domain or workgroup as\n\tthe default.\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+int net_rap_server(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ d_printf("\nEnumerating servers in this domain or workgroup: \n\n"\
+ "\tServer name Server description\n"\
+ "\t------------- ----------------------------\n");
+
+ ret = cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL,
+ display_server_func,NULL);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_domain_usage(int argc, const char **argv)
+{
+ d_printf("net rap domain [misc. options] [target]\n\tlists the"\
+ " domains or workgroups visible on the current network\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+
+int net_rap_domain(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ d_printf("\nEnumerating domains:\n\n"\
+ "\tDomain name Server name of Browse Master\n"\
+ "\t------------- ----------------------------\n");
+
+ ret = cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
+ display_server_func,NULL);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_printq_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net rap printq [misc. options] [targets]\n"\
+ "\tor\n"\
+ "net rap printq list [<queue_name>] [misc. options] [targets]\n"\
+ "\tlists the specified queue and jobs on the target server.\n"\
+ "\tIf the queue name is not specified, all queues are listed.\n\n");
+ d_printf(
+ "net rap printq delete [<queue name>] [misc. options] [targets]\n"\
+ "\tdeletes the specified job number on the target server, or the\n"\
+ "\tprinter queue if no job number is specified\n");
+
+ net_common_flags_usage(argc, argv);
+ d_printf("\t-j or --jobid=<job id>\t\tjob id\n");
+
+ return -1;
+}
+
+static void enum_queue(const char *queuename, uint16 pri, uint16 start,
+ uint16 until, const char *sep, const char *pproc,
+ const char *dest, const char *qparms,
+ const char *qcomment, uint16 status, uint16 jobcount)
+{
+ d_printf("%-17.17s Queue %5d jobs ",
+ queuename, jobcount);
+
+ switch (status) {
+ case 0:
+ d_printf("*Printer Active*\n");
+ break;
+ case 1:
+ d_printf("*Printer Paused*\n");
+ break;
+ case 2:
+ d_printf("*Printer error*\n");
+ break;
+ case 3:
+ d_printf("*Delete Pending*\n");
+ break;
+ default:
+ d_printf("**UNKNOWN STATUS**\n");
+ }
+}
+
+static void enum_jobs(uint16 jobid, const char *ownername,
+ const char *notifyname, const char *datatype,
+ const char *jparms, uint16 pos, uint16 status,
+ const char *jstatus, uint submitted, uint jobsize,
+ const char *comment)
+{
+ d_printf(" %-23.23s %5d %9d ",
+ ownername, jobid, jobsize);
+ switch (status) {
+ case 0:
+ d_printf("Waiting\n");
+ break;
+ case 1:
+ d_printf("Held in queue\n");
+ break;
+ case 2:
+ d_printf("Spooling\n");
+ break;
+ case 3:
+ d_printf("Printing\n");
+ break;
+ default:
+ d_printf("**UNKNOWN STATUS**\n");
+ }
+}
+
+#define PRINTQ_ENUM_DISPLAY \
+ "Print queues at \\\\%s\n\n"\
+ "Name Job # Size Status\n\n"\
+ "------------------------------------------------------------------"\
+ "-------------\n"
+
+static int rap_printq_info(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (argc == 0)
+ return net_rap_printq_usage(argc, argv);
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ d_printf(PRINTQ_ENUM_DISPLAY, cli->desthost); /* list header */
+ ret = cli_NetPrintQGetInfo(cli, argv[0], enum_queue, enum_jobs);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_printq_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (argc == 0)
+ return net_rap_printq_usage(argc, argv);
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_printjob_del(cli, atoi(argv[0]));
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_printq(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ struct functable func[] = {
+ {"INFO", rap_printq_info},
+ {"DELETE", rap_printq_delete},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ d_printf(PRINTQ_ENUM_DISPLAY, cli->desthost); /* list header */
+ ret = cli_NetPrintQEnum(cli, enum_queue, enum_jobs);
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_printq_usage);
+}
+
+
+static int net_rap_user_usage(int argc, const char **argv)
+{
+ return net_help_user(argc, argv);
+}
+
+static void user_fn(const char *user_name, const char *comment,
+ const char * home_dir, const char * logon_script,
+ void *state)
+{
+ d_printf("%-21.21s\n", user_name);
+}
+
+static void long_user_fn(const char *user_name, const char *comment,
+ const char * home_dir, const char * logon_script,
+ void *state)
+{
+ d_printf("%-21.21s %-50.50s\n",
+ user_name, comment);
+}
+
+static void group_member_fn(const char *user_name, void *state)
+{
+ d_printf("%-21.21s\n", user_name);
+}
+
+static int rap_user_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (argc == 0) {
+ d_printf("\n\nUser name not specified\n");
+ return net_rap_user_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetUserDelete(cli, argv[0]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_user_add(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ RAP_USER_INFO_1 userinfo;
+
+ if (argc == 0) {
+ d_printf("\n\nUser name not specified\n");
+ return net_rap_user_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ safe_strcpy(userinfo.user_name, argv[0], sizeof(userinfo.user_name));
+ if (opt_flags == -1)
+ opt_flags = 0x21;
+
+ userinfo.userflags = opt_flags;
+ userinfo.reserved1 = '\0';
+ userinfo.comment = opt_comment;
+ userinfo.priv = 1;
+ userinfo.home_dir = NULL;
+ userinfo.logon_script = NULL;
+
+ ret = cli_NetUserAdd(cli, &userinfo);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_user_info(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc == 0) {
+ d_printf("\n\nUser name not specified\n");
+ return net_rap_user_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetUserGetGroups(cli, argv[0], group_member_fn, NULL);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_user(int argc, const char **argv)
+{
+ int ret = -1;
+ struct functable func[] = {
+ {"ADD", rap_user_add},
+ {"INFO", rap_user_info},
+ {"DELETE", rap_user_delete},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ if (!(cli = net_make_ipc_connection(0)))
+ goto done;
+ if (opt_long_list_entries) {
+ d_printf("\nUser name Comment"\
+ "\n-----------------------------\n");
+ ret = cli_RNetUserEnum(cli, long_user_fn, NULL);
+ cli_shutdown(cli);
+ goto done;
+ }
+ ret = cli_RNetUserEnum(cli, user_fn, NULL);
+ cli_shutdown(cli);
+ goto done;
+ }
+
+ ret = net_run_function(argc, argv, func, net_rap_user_usage);
+ done:
+ if (ret != 0) {
+ DEBUG(1, ("Net user returned: %d\n", ret));
+ }
+ return ret;
+}
+
+
+int net_rap_group_usage(int argc, const char **argv)
+{
+ d_printf("net rap group [misc. options] [targets]"\
+ "\n\tList user groups\n");
+ d_printf("\nnet rap group DELETE <name> [misc. options] [targets]"\
+ "\n\tDelete specified group\n");
+ d_printf("\nnet rap group ADD <name> [-C comment] [misc. options]"\
+ " [targets]\n\tCreate specified group\n");
+
+ net_common_flags_usage(argc, argv);
+ d_printf(
+ "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n");
+ return -1;
+}
+
+static void long_group_fn(const char *group_name, const char *comment,
+ void *state)
+{
+ d_printf("%-21.21s %-50.50s\n", group_name, comment);
+}
+
+static void group_fn(const char *group_name, const char *comment, void *state)
+{
+ d_printf("%-21.21s\n", group_name);
+}
+
+static int rap_group_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc == 0) {
+ d_printf("\n\nGroup name not specified\n");
+ return net_rap_group_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetGroupDelete(cli, argv[0]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_group_add(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ RAP_GROUP_INFO_1 grinfo;
+
+ if (argc == 0) {
+ d_printf("\n\nGroup name not specified\n");
+ return net_rap_group_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ /* BB check for length 21 or smaller explicitly ? BB */
+ safe_strcpy(grinfo.group_name, argv[0], sizeof(grinfo.group_name));
+ grinfo.reserved1 = '\0';
+ grinfo.comment = opt_comment;
+
+ ret = cli_NetGroupAdd(cli, &grinfo);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_group(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"ADD", rap_group_add},
+ {"DELETE", rap_group_delete},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ int ret;
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+ if (opt_long_list_entries) {
+ d_printf("Group name Comment\n");
+ d_printf("-----------------------------\n");
+ ret = cli_RNetGroupEnum(cli, long_group_fn, NULL);
+ cli_shutdown(cli);
+ return ret;
+ }
+ ret = cli_RNetGroupEnum(cli, group_fn, NULL);
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_group_usage);
+}
+
+int net_rap_groupmember_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net rap groupmember LIST <group> [misc. options] [targets]"\
+ "\n\t Enumerate users in a group\n"\
+ "\nnet rap groupmember DELETE <group> <user> [misc. options] "\
+ "[targets]\n\t Delete sepcified user from specified group\n"\
+ "\nnet rap groupmember ADD <group> <user> [misc. options] [targets]"\
+ "\n\t Add specified user to specified group\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+
+static int rap_groupmember_add(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc != 2) {
+ d_printf("\n\nGroup or user name not specified\n");
+ return net_rap_groupmember_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetGroupAddUser(cli, argv[0], argv[1]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_groupmember_delete(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc != 2) {
+ d_printf("\n\nGroup or user name not specified\n");
+ return net_rap_groupmember_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetGroupDelUser(cli, argv[0], argv[1]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+static int rap_groupmember_list(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+ if (argc == 0) {
+ d_printf("\n\nGroup name not specified\n");
+ return net_rap_groupmember_usage(argc, argv);
+ }
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ ret = cli_NetGroupGetUsers(cli, argv[0], group_member_fn, NULL );
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_groupmember(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"ADD", rap_groupmember_add},
+ {"LIST", rap_groupmember_list},
+ {"DELETE", rap_groupmember_delete},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_rap_groupmember_usage);
+}
+
+int net_rap_validate_usage(int argc, const char **argv)
+{
+ d_printf("net rap validate <username> [password]\n"\
+ "\tValidate user and password to check whether they"\
+ " can access target server or domain\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+int net_rap_validate(int argc, const char **argv)
+{
+ return errmsg_not_implemented();
+}
+
+int net_rap_service_usage(int argc, const char **argv)
+{
+ d_printf("net rap service [misc. options] [targets] \n"\
+ "\tlists all running service daemons on target server\n");
+ d_printf("\nnet rap service START <name> [service startup arguments]"\
+ " [misc. options] [targets]"\
+ "\n\tStart named service on remote server\n");
+ d_printf("\nnet rap service STOP <name> [misc. options] [targets]\n"\
+ "\n\tStop named service on remote server\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+static int rap_service_start(int argc, const char **argv)
+{
+ return errmsg_not_implemented();
+}
+
+static int rap_service_stop(int argc, const char **argv)
+{
+ return errmsg_not_implemented();
+}
+
+int net_rap_service(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"START", rap_service_start},
+ {"STOP", rap_service_stop},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ struct cli_state *cli;
+ int ret;
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (opt_long_list_entries) {
+ d_printf("Service name Comment\n");
+ d_printf("-----------------------------\n");
+ ret = cli_RNetServiceEnum(cli, long_group_fn, NULL);
+ }
+ ret = cli_RNetServiceEnum(cli, group_fn, NULL);
+ cli_shutdown(cli);
+ return ret;
+ }
+
+ return net_run_function(argc, argv, func, net_rap_service_usage);
+}
+
+int net_rap_password_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net rap password <user> <oldpwo> <newpw> [misc. options] [target]\n"\
+ "\tchanges the password for the specified user at target\n");
+
+ return -1;
+}
+
+
+int net_rap_password(int argc, const char **argv)
+{
+ struct cli_state *cli;
+ int ret;
+
+ if (argc < 3)
+ return net_rap_password_usage(argc, argv);
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ /* BB Add check for password lengths? */
+ ret = cli_oem_change_password(cli, argv[0], argv[2], argv[1]);
+ cli_shutdown(cli);
+ return ret;
+}
+
+int net_rap_admin_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net rap admin <remote command> [cmd args [env]] [misc. options] [targets]"\
+ "\n\texecutes a remote command on an os/2 target server\n");
+
+ return -1;
+}
+
+
+int net_rap_admin(int argc, const char **argv)
+{
+ return errmsg_not_implemented();
+}
+
+/* The help subsystem for the RAP subcommand */
+
+int net_rap_usage(int argc, const char **argv)
+{
+ d_printf(" net rap domain \tto list domains \n"\
+ " net rap file \t\tto list open files on a server \n"\
+ " net rap group \tto list user groups \n"\
+ " net rap groupmember \tto list users in a group \n"\
+ " net rap password \tto change the password of a user\n"\
+ " net rap printq \tto list the print queues on a server\n"\
+ " net rap server \tto list servers in a domain\n"\
+ " net rap session \tto list clients with open sessions to a server\n"\
+ " net rap share \tto list shares exported by a server\n"\
+ " net rap user \t\tto list users\n"\
+ " net rap validate \tto check whether a user and the corresponding password are valid\n"\
+ " net rap help\n"\
+ "\nType \"net help <option>\" to get more information on that option\n\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+/*
+ handle "net rap help *" subcommands
+*/
+int net_rap_help(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"FILE", net_rap_file_usage},
+ {"SHARE", net_rap_share_usage},
+ {"SESSION", net_rap_session_usage},
+ {"SERVER", net_rap_server_usage},
+ {"DOMAIN", net_rap_domain_usage},
+ {"PRINTQ", net_rap_printq_usage},
+ {"USER", net_rap_user_usage},
+ {"GROUP", net_rap_group_usage},
+ {"VALIDATE", net_rap_validate_usage},
+ {"GROUPMEMBER", net_rap_groupmember_usage},
+ {"ADMIN", net_rap_admin_usage},
+ {"SERVICE", net_rap_service_usage},
+ {"PASSWORD", net_rap_password_usage},
+ {NULL, NULL}};
+
+ return net_run_function(argc, argv, func, net_rap_usage);
+}
+
+/* Entry-point for all the RAP functions. */
+
+int net_rap(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"FILE", net_rap_file},
+ {"SHARE", net_rap_share},
+ {"SESSION", net_rap_session},
+ {"SERVER", net_rap_server},
+ {"DOMAIN", net_rap_domain},
+ {"PRINTQ", net_rap_printq},
+ {"USER", net_rap_user},
+ {"GROUP", net_rap_group},
+ {"VALIDATE", net_rap_validate},
+ {"GROUPMEMBER", net_rap_groupmember},
+ {"ADMIN", net_rap_admin},
+ {"SERVICE", net_rap_service},
+ {"PASSWORD", net_rap_password},
+ {"HELP", net_rap_help},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_rap_usage);
+}
+
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
new file mode 100644
index 0000000000..19e2c63ecc
--- /dev/null
+++ b/source3/utils/net_rpc.c
@@ -0,0 +1,1328 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+
+ 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 "../utils/net.h"
+
+extern pstring global_myname;
+
+/**
+ * @file net_rpc.c
+ *
+ * @brief RPC based subcommands for the 'net' utility.
+ *
+ * This file should contain much of the functionality that used to
+ * be found in rpcclient, execpt that the commands should change
+ * less often, and the fucntionality should be sane (the user is not
+ * expected to know a rid/sid before they conduct an operation etc.)
+ *
+ * @todo Perhaps eventually these should be split out into a number
+ * of files, as this could get quite big.
+ **/
+
+
+/* A function of this type is passed to the 'run_rpc_command' wrapper */
+typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
+
+/**
+ * Many of the RPC functions need the domain sid. This function gets
+ * it at the start of every run
+ *
+ * @param cli A cli_state already connected to the remote machine
+ *
+ * @return The Domain SID of the remote machine.
+ **/
+
+static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
+{
+ DOM_SID *domain_sid;
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_OK;
+ uint32 info_class = 5;
+ fstring domain_name;
+ TALLOC_CTX *mem_ctx;
+
+ if (!(domain_sid = malloc(sizeof(DOM_SID)))){
+ DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
+ goto error;
+ }
+
+ if (!(mem_ctx=talloc_init()))
+ {
+ DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
+ goto error;
+ }
+
+
+ if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
+ fprintf(stderr, "could not initialise lsa pipe\n");
+ goto error;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
+ domain_name, domain_sid);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ cli_lsa_close(cli, mem_ctx, &pol);
+ cli_nt_session_close(cli);
+ talloc_destroy(mem_ctx);
+
+ return domain_sid;
+
+ error:
+ fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "error: %s\n", nt_errstr(result));
+ }
+
+ exit(1);
+}
+
+/**
+ * Run a single RPC command, from start to finish.
+ *
+ * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
+ * @param conn_flag a NET_FLAG_ combination. Passed to
+ * net_make_ipc_connection.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ * @return A shell status integer (0 for success)
+ */
+
+static int run_rpc_command(const char *pipe_name, int conn_flags,
+ rpc_command_fn fn,
+ int argc, const char **argv)
+{
+ struct cli_state *cli = net_make_ipc_connection(conn_flags);
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS nt_status;
+ DOM_SID *domain_sid;
+
+ if (!cli) {
+ return -1;
+ }
+
+ domain_sid = net_get_remote_domain_sid(cli);
+
+ /* Create mem_ctx */
+
+ if (!(mem_ctx = talloc_init())) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ if (!cli_nt_session_open(cli, pipe_name)) {
+ DEBUG(0, ("Could not initialise samr pipe\n"));
+ }
+
+ nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
+ } else {
+ DEBUG(5, ("rpc command function succedded\n"));
+ }
+
+
+ if (cli->nt_pipe_fnum)
+ cli_nt_session_close(cli);
+
+ talloc_destroy(mem_ctx);
+
+ return (!NT_STATUS_IS_OK(nt_status));
+}
+
+
+/****************************************************************************/
+
+
+/**
+ * Force a change of the trust acccount password.
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
+}
+
+/**
+ * Force a change of the trust acccount password.
+ *
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_changetrustpw(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
+ argc, argv);
+}
+
+
+/****************************************************************************/
+
+
+/**
+ * Join a domain, the old way.
+ *
+ * This uses 'machinename' as the inital password, and changes it.
+ *
+ * The password should be created with 'server manager' or eqiv first.
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ extern pstring global_myname;
+ fstring trust_passwd;
+ unsigned char orig_trust_passwd_hash[16];
+
+ fstrcpy(trust_passwd, global_myname);
+ strlower(trust_passwd);
+ E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
+
+ return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
+}
+
+/**
+ * Join a domain, the old way.
+ *
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int net_rpc_join_oldstyle(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
+ argc, argv);
+}
+
+/**
+ * Basic usage function for 'net rpc join'
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+static int rpc_join_usage(int argc, const char **argv)
+{
+ d_printf("net rpc join -U <username>[%%password] [options]\n"\
+ "\t to join a domain with admin username & password\n"\
+ "\t\t password will be prompted if none is specified\n");
+ d_printf("net rpc join [options except -U]\n"\
+ "\t to join a domain created in server manager\n\n\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+/**
+ * 'net rpc join' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * Main 'net_rpc_join()' (where the admain username/password is used) is
+ * in net_rpc_join.c
+ * Assume if a -U is specified, it's the new style, otherwise it's the
+ * old style
+ **/
+
+int net_rpc_join(int argc, const char **argv)
+{
+ if ((net_rpc_join_oldstyle(argc, argv) == 0))
+ return 0;
+
+ return net_rpc_join_newstyle(argc, argv);
+}
+
+
+/****************************************************************************/
+
+/**
+ * Basic usage function for 'net rpc user'
+ * @param argc Standard main() style argc.
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped.
+ **/
+
+static int rpc_user_usage(int argc, const char **argv)
+{
+ return net_help_user(argc, argv);
+}
+
+/**
+ * Add a new user to a remote RPC server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *acct_name;
+ uint16 acb_info;
+ uint32 unknown, user_rid;
+
+ if (argc != 1) {
+ d_printf("User must be specified\n");
+ rpc_user_usage(argc, argv);
+ return NT_STATUS_OK;
+ }
+
+ acct_name = argv[0];
+
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Create domain user */
+
+ acb_info = ACB_NORMAL;
+ unknown = 0xe005000b; /* No idea what this is - a permission mask? */
+
+ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+ acct_name, acb_info, unknown,
+ &user_pol, &user_rid);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ if (!NT_STATUS_IS_OK(result)) {
+ d_printf("Failed to add user %s - %s\n", acct_name,
+ nt_errstr(result));
+ } else {
+ d_printf("Added user %s\n", acct_name);
+ }
+ return result;
+}
+
+/**
+ * Add a new user to a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_user_add(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
+ argc, argv);
+}
+
+/**
+ * Delete a user from a remote RPC server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
+ struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol, user_pol;
+
+ if (argc < 1) {
+ d_printf("User must be specified\n");
+ rpc_user_usage(argc, argv);
+ return NT_STATUS_OK;
+ }
+ /* Get sam policy and domain handles */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get handle on user */
+
+ {
+ uint32 *user_rids, num_rids, *name_types;
+ uint32 flags = 0x000003e8; /* Unknown */
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+ flags, 1, (char **) &argv[0],
+ &num_rids, &user_rids,
+ &name_types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ user_rids[0], &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+ }
+
+ /* Delete user */
+
+ result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ done:
+ return result;
+
+}
+
+/**
+ * Delete a user from a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_user_delete(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_SAMR, 0, rpc_user_del_internals,
+ argc, argv);
+}
+
+/**
+ * List user's groups on a remote RPC server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS
+rpc_user_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 *rids, num_rids, *name_types, num_names;
+ uint32 flags = 0x000003e8; /* Unknown */
+ int i;
+ char **names;
+ DOM_GID *user_gids;
+
+ if (argc < 1) {
+ d_printf("User must be specified\n");
+ rpc_user_usage(argc, argv);
+ return NT_STATUS_OK;
+ }
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ /* Get handle on user */
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+ flags, 1, (char **) &argv[0],
+ &num_rids, &rids, &name_types);
+
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ rids[0], &user_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
+ &num_rids, &user_gids);
+
+ /* Look up rids */
+
+ rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
+
+ for (i = 0; i < num_rids; i++)
+ rids[i] = user_gids[i].g_rid;
+
+ result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
+ flags, num_rids, rids,
+ &num_names, &names, &name_types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ for (i = 0; i < num_names; i++)
+ printf("%s\n", names[i]);
+
+ done:
+ return result;
+}
+
+/**
+ * List a user's groups from a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_user_info(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_SAMR, 0, rpc_user_info_internals,
+ argc, argv);
+}
+
+/**
+ * List users on a remote RPC server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS
+rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx=0, max_entries=250, num_entries, i;
+ SAM_DISPINFO_CTR ctr;
+ SAM_DISPINFO_1 info1;
+
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Query domain users */
+ ZERO_STRUCT(ctr);
+ ZERO_STRUCT(info1);
+ ctr.sam.info1 = &info1;
+ if (opt_long_list_entries)
+ d_printf("\nUser name Comment"\
+ "\n-----------------------------\n");
+ do {
+ fstring user, desc;
+ result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
+ &start_idx, 1, &num_entries,
+ max_entries, &ctr);
+ for (i = 0; i < num_entries; i++) {
+ unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
+ if (opt_long_list_entries)
+ unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
+
+ if (opt_long_list_entries)
+ printf("%-21.21s %-50.50s\n", user, desc);
+ else
+ printf("%-21.21s\n", user);
+ }
+ } while (!NT_STATUS_IS_OK(result));
+
+ done:
+ return result;
+}
+
+/**
+ * 'net rpc user' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int net_rpc_user(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"add", rpc_user_add},
+ {"info", rpc_user_info},
+ {"delete", rpc_user_delete},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ if (opt_long_list_entries) {
+ } else {
+ }
+ return run_rpc_command(PIPE_SAMR, 0,
+ rpc_user_list_internals,
+ argc, argv);
+ }
+
+ return net_run_function(argc, argv, func, rpc_user_usage);
+}
+
+
+/****************************************************************************/
+
+
+
+/**
+ * ABORT the shutdown of a remote RPC Server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ result = cli_reg_abort_shutdown(cli, mem_ctx);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
+ else
+ DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
+
+ return result;
+}
+
+
+/**
+ * ABORT the Shut down of a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_shutdown_abort(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
+ argc, argv);
+}
+
+/**
+ * Shut down a remote RPC Server
+ *
+ * All paramaters are provided by the run_rpc_command funcion, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ char *msg = "This machine will be shutdown shortly";
+ uint32 timeout = 20;
+ uint16 flgs = 0;
+ BOOL reboot = opt_reboot;
+ BOOL force = opt_force;
+#if 0
+ poptContext pc;
+ int rc;
+
+ struct poptOption long_options[] = {
+ {"message", 'm', POPT_ARG_STRING, &msg},
+ {"timeout", 't', POPT_ARG_INT, &timeout},
+ {"reboot", 'r', POPT_ARG_NONE, &reboot},
+ {"force", 'f', POPT_ARG_NONE, &force},
+ { 0, 0, 0, 0}
+ };
+
+ pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ rc = poptGetNextOpt(pc);
+
+ if (rc < -1) {
+ /* an error occurred during option processing */
+ DEBUG(0, ("%s: %s\n",
+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
+ poptStrerror(rc)));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+#endif
+ if (reboot) {
+ flgs |= REG_REBOOT_ON_SHUTDOWN;
+ }
+ if (force) {
+ flgs |= REG_FORCE_SHUTDOWN;
+ }
+ if (opt_comment) {
+ msg = opt_comment;
+ }
+ if (opt_timeout) {
+ timeout = opt_timeout;
+ }
+
+ /* create an entry */
+ result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("Shutdown of remote machine succeeded\n"));
+ else
+ DEBUG(0,("Shutdown of remote machine failed!\n"));
+
+ return result;
+}
+
+/**
+ * Shut down a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+
+static int rpc_shutdown(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
+ argc, argv);
+}
+
+/***************************************************************************
+ NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
+
+ ***************************************************************************/
+
+/**
+ * Add interdomain trust account to the RPC server.
+ * All parameters (except for argc and argv) are passed by run_rpc_command
+ * function.
+ *
+ * @param domain_sid The domain sid acquired from the server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return normal NTSTATUS return code
+ */
+
+static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ char *acct_name;
+ uint16 acb_info;
+ uint32 unknown, user_rid;
+
+ if (argc != 1) {
+ d_printf("Usage: net rpc trustdom add <domain_name>\n");
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * Make valid trusting domain account (ie. uppercased and with '$' appended)
+ */
+
+ if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ strupper(acct_name);
+
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Create trusting domain's account */
+
+ acb_info = ACB_DOMTRUST;
+ unknown = 0xe005000b; /* No idea what this is - a permission mask?
+ Is it needed for interdomain account also ? */
+
+ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+ acct_name, acb_info, unknown,
+ &user_pol, &user_rid);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ SAFE_FREE(acct_name);
+ return result;
+}
+
+/**
+ * Create interdomain trust account for a remote domain.
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ **/
+
+static int rpc_trustdom_add(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
+ argc, argv);
+}
+
+
+/**
+ * Delete interdomain trust account for a remote domain.
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ **/
+
+static int rpc_trustdom_del(int argc, const char **argv)
+{
+ d_printf("Sorry, not yet implemented.\n");
+ return -1;
+}
+
+
+/**
+ * Establish trust relationship to a trusting domain.
+ * Interdomain account must already be created on remote PDC.
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ **/
+
+extern char *opt_user_name;
+extern char *opt_password;
+
+static int rpc_trustdom_establish(int argc, const char **argv) {
+
+ struct cli_state *cli;
+ struct in_addr server_ip;
+ POLICY_HND connect_hnd;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS nt_status;
+ DOM_SID domain_sid;
+ WKS_INFO_100 wks_info;
+
+ char* domain_name;
+ char* acct_name;
+ fstring pdc_name;
+
+ /*
+ * Connect to \\server\ipc$ as 'our domain' account with password
+ */
+
+ domain_name = smb_xstrdup(argv[0]);
+ strupper(domain_name);
+
+ asprintf(&acct_name, "%s$", lp_workgroup());
+ strupper(acct_name);
+
+ opt_user_name = (char*)malloc(strlen(acct_name) + 1);
+ safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
+
+ /* find the domain controller */
+ if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
+ DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
+ return -1;
+ }
+
+ /* connect to ipc$ as username/password */
+ nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
+
+ /* Is it trusting domain account for sure ? */
+ DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
+ nt_errstr(nt_status)));
+ return -1;
+ }
+
+ /*
+ * Connect to \\server\ipc$ again (this time anonymously)
+ */
+
+ nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
+
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
+ domain_name, nt_errstr(nt_status)));
+ }
+
+ /*
+ * Use NetServerEnum2 to make sure we're talking to a proper server
+ */
+
+ if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
+ DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
+ for domain %s\n", domain_name));
+ }
+
+ /*
+ * Call WksQueryInfo to check remote server's capabilities
+ * FIXME:Is really necessary ? nt serv does this, but from samba's
+ * point of view it doesn't seem to make the difference
+ * IDEA: It may be used to get info about type of pdc we're talking to
+ * (e.g. WinNT or Win2k)
+ */
+
+ if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
+ DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
+ return -1;
+ }
+
+ /* TODO: convert this call from rpc_client/cli_wkssvc.c
+ to cli_wks_query_info() in libsmb/cli_wkssvc.c
+ UPDATE: already done :)
+ */
+
+ if (!(mem_ctx = talloc_init())) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
+
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("WksQueryInfo call failed.\n"));
+ return -1;
+ }
+
+ if (cli->nt_pipe_fnum) {
+ cli_nt_session_close(cli);
+ talloc_destroy(mem_ctx);
+ }
+
+
+ /*
+ * Call LsaOpenPolicy and LsaQueryInfo
+ */
+
+ if (!(mem_ctx = talloc_init())) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
+ DEBUG(0, ("Could not initialise lsa pipe\n"));
+ }
+
+ nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
+ &connect_hnd);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
+ nt_errstr(nt_status)));
+ return -1;
+ }
+
+ /* Querying info level 5 */
+
+ nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
+ 5 /* info level */, domain_name, &domain_sid);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
+ nt_errstr(nt_status)));
+ return -1;
+ }
+
+
+ /* There should be actually query info level 3 (following nt serv behaviour),
+ but I still don't know if it's _really_ necessary */
+
+ /*
+ * Close the pipes and clean up
+ */
+
+ nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
+ nt_errstr(nt_status)));
+ return -1;
+ }
+
+ if (cli->nt_pipe_fnum)
+ cli_nt_session_close(cli);
+
+ talloc_destroy(mem_ctx);
+
+
+ /*
+ * Store the password in secrets db
+ */
+
+ if (!secrets_store_trusted_domain_password(domain_name, opt_password,
+ domain_sid)) {
+ DEBUG(0, ("Storing password for trusted domain failed.\n"));
+ return -1;
+ }
+
+ DEBUG(0, ("Success!\n"));
+ return 0;
+}
+
+/**
+ * Revoke trust relationship to the remote domain
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ **/
+
+static int rpc_trustdom_revoke(int argc, const char **argv) {
+
+ char* domain_name;
+
+ if (argc < 1) return -1;
+
+ /* generate upper cased domain name */
+ domain_name = smb_xstrdup(argv[0]);
+ strupper(domain_name);
+
+ /* delete password of the trust */
+ if (!trusted_domain_password_delete(domain_name)) {
+ DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
+ domain_name));
+ return -1;
+ };
+
+ return 0;
+}
+
+/**
+ * Usage for 'net rpc trustdom' command
+ *
+ * @param argc standard argc
+ * @param argv standard argv without inital components
+ *
+ * @return Integer status returned to shell
+ **/
+
+static int rpc_trustdom_usage(int argc, const char **argv) {
+ d_printf(" net rpc trustdom add \t\t add trusting domain's account\n");
+ d_printf(" net rpc trustdom del \t\t delete trusting domain's account\n");
+ d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n");
+ d_printf(" net rpc trustdom revoke \t abandon relationship to trusted domain\n");
+ d_printf(" net rpc trustdom list \t show current interdomain trust relationships\n");
+ return -1;
+}
+
+
+/**
+ * Entrypoint for 'net rpc trustdom' code
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ */
+
+static int rpc_trustdom(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"add", rpc_trustdom_add},
+ {"del", rpc_trustdom_del},
+ {"establish", rpc_trustdom_establish},
+ {"revoke", rpc_trustdom_revoke},
+ {"help", rpc_trustdom_usage},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ rpc_trustdom_usage(argc, argv);
+ return -1;
+ }
+
+ return (net_run_function(argc, argv, func, rpc_user_usage));
+}
+
+/**
+ * Check if a server will take rpc commands
+ * @param flags Type of server to connect to (PDC, DMB, localhost)
+ * if the host is not explicitly specified
+ * @return BOOL (true means rpc supported)
+ */
+BOOL net_rpc_check(unsigned flags)
+{
+ struct cli_state cli;
+ BOOL ret = False;
+ struct in_addr server_ip;
+ char *server_name = NULL;
+
+ /* flags (i.e. server type) may depend on command */
+ if (!net_find_server(flags, &server_ip, &server_name))
+ goto done;
+
+ ZERO_STRUCT(cli);
+ if (cli_initialise(&cli) == False)
+ return False;
+
+ if (!cli_connect(&cli, server_name, &server_ip))
+ goto done;
+ if (!attempt_netbios_session_request(&cli, global_myname,
+ server_name, &server_ip))
+ goto done;
+ if (!cli_negprot(&cli))
+ goto done;
+ if (cli.protocol < PROTOCOL_NT1)
+ goto done;
+
+ ret = True;
+ done:
+ cli_shutdown(&cli);
+ return ret;
+}
+
+
+/****************************************************************************/
+
+
+/**
+ * Basic usage function for 'net rpc'
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int net_rpc_usage(int argc, const char **argv)
+{
+ d_printf(" net rpc join \t\t\tto join a domain \n");
+ d_printf(" net rpc user \t\t\tto add, delete and list users\n");
+ d_printf(" net rpc changetrustpw \tto change the trust account password\n");
+ d_printf(" net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
+ d_printf(" net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
+ d_printf(" net rpc shutdown \t\tto to shutdown a remote server\n");
+ d_printf("\n");
+ d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
+ d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
+ d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
+ d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
+ d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
+ return -1;
+}
+
+
+/**
+ * Help function for 'net rpc'. Calls command specific help if requested
+ * or displays usage of net rpc
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int net_rpc_help(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"join", rpc_join_usage},
+ {"user", net_help_user},
+ /*{"changetrustpw", rpc_changetrustpw_usage}, */
+ {"trustdom", rpc_trustdom_usage},
+ /*{"abortshutdown", rpc_shutdown_abort_usage},*/
+ /*{"shutdown", rpc_shutdown_usage}, */
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ net_rpc_usage(argc, argv);
+ return -1;
+ }
+
+ return (net_run_function(argc, argv, func, rpc_user_usage));
+}
+
+
+/**
+ * 'net rpc' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int net_rpc(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"join", net_rpc_join},
+ {"user", net_rpc_user},
+ {"changetrustpw", rpc_changetrustpw},
+ {"trustdom", rpc_trustdom},
+ {"abortshutdown", rpc_shutdown_abort},
+ {"shutdown", rpc_shutdown},
+ {"help", net_rpc_help},
+ {NULL, NULL}
+ };
+ return net_run_function(argc, argv, func, net_rpc_usage);
+}
diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c
new file mode 100644
index 0000000000..c4558ea10b
--- /dev/null
+++ b/source3/utils/net_rpc_join.c
@@ -0,0 +1,303 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+ Copyright (C) Tim Potter 2001
+
+ 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 "../utils/net.h"
+
+/* Macro for checking RPC error codes to make things more readable */
+
+#define CHECK_RPC_ERR(rpc, msg) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
+ goto done; \
+ }
+
+#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, debug_args); \
+ goto done; \
+ }
+
+/**
+ * Join a domain using the administrator username and password
+ *
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped. Currently not used.
+ * @return A shell status integer (0 for success)
+ *
+ **/
+
+int net_rpc_join_newstyle(int argc, const char **argv)
+{
+
+ extern pstring global_myname;
+
+ /* libsmb variables */
+
+ struct cli_state *cli;
+ fstring acct_name;
+ TALLOC_CTX *mem_ctx;
+ uint32 acb_info;
+
+ /* rpc variables */
+
+ POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol;
+ DOM_SID domain_sid;
+ uint32 user_rid;
+
+ /* Password stuff */
+
+ char *clear_trust_password = NULL;
+ fstring ucs2_trust_password;
+ int ucs2_pw_len;
+ uchar stored_md4_trust_password[16];
+ uchar pwbuf[516], sess_key[16];
+ SAM_USERINFO_CTR ctr;
+ SAM_USER_INFO_24 p24;
+ SAM_USER_INFO_10 p10;
+
+ /* Misc */
+
+ NTSTATUS result;
+ int retval = 1;
+ fstring domain;
+ uint32 num_rids, *name_types, *user_rids;
+ uint32 flags = 0x3e8;
+ char *names;
+
+ /* Connect to remote machine */
+
+ if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC)))
+ return 1;
+
+ if (!(mem_ctx = talloc_init())) {
+ DEBUG(0, ("Could not initialise talloc context\n"));
+ goto done;
+ }
+
+ /* Fetch domain sid */
+
+ if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
+ DEBUG(0, ("Error connecting to SAM pipe\n"));
+ goto done;
+ }
+
+
+ CHECK_RPC_ERR(cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &lsa_pol),
+ "error opening lsa policy handle");
+
+ CHECK_RPC_ERR(cli_lsa_query_info_policy(cli, mem_ctx, &lsa_pol,
+ 5, domain, &domain_sid),
+ "error querying info policy");
+
+ cli_lsa_close(cli, mem_ctx, &lsa_pol);
+
+ cli_nt_session_close(cli); /* Done with this pipe */
+
+ /* Create domain user */
+ if (!cli_nt_session_open(cli, PIPE_SAMR)) {
+ DEBUG(0, ("Error connecting to SAM pipe\n"));
+ goto done;
+ }
+
+ CHECK_RPC_ERR(cli_samr_connect(cli, mem_ctx,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &sam_pol),
+ "could not connect to SAM database");
+
+
+ CHECK_RPC_ERR(cli_samr_open_domain(cli, mem_ctx, &sam_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain_sid, &domain_pol),
+ "could not open domain");
+
+ /* Create domain user */
+ fstrcpy(acct_name, global_myname);
+ fstrcat(acct_name, "$");
+ strlower(acct_name);
+
+ acb_info = ((lp_server_role() == ROLE_DOMAIN_BDC) || lp_server_role() == ROLE_DOMAIN_PDC) ? ACB_SVRTRUST : ACB_WSTRUST;
+
+ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+ acct_name, acb_info,
+ 0xe005000b, &user_pol,
+ &user_rid);
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) {
+ d_printf("Create of workstation account failed\n");
+
+ /* If NT_STATUS_ACCESS_DENIED then we have a valid
+ username/password combo but the user does not have
+ administrator access. */
+
+ if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
+ d_printf("User specified does not have administrator privileges\n");
+
+ goto done;
+ }
+
+ /* We *must* do this.... don't ask... */
+
+ if (NT_STATUS_IS_OK(result))
+ cli_samr_close(cli, mem_ctx, &user_pol);
+
+ names = (char *)&acct_name[0];
+
+ CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx,
+ &domain_pol, flags,
+ 1, &names, &num_rids,
+ &user_rids, &name_types),
+ ("error looking up rid for user %s: %s\n",
+ acct_name, nt_errstr(result)));
+
+ if (name_types[0] != SID_NAME_USER) {
+ DEBUG(0, ("%s is not a user account\n", acct_name));
+ goto done;
+ }
+
+ user_rid = user_rids[0];
+
+ /* Open handle on user */
+
+ CHECK_RPC_ERR_DEBUG(
+ cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ user_rid, &user_pol),
+ ("could not re-open existing user %s: %s\n",
+ acct_name, nt_errstr(result)));
+
+ /* Create a random machine account password */
+
+ {
+ char *str;
+ str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ clear_trust_password = strdup(str);
+ }
+
+ ucs2_pw_len = push_ucs2(NULL, ucs2_trust_password,
+ clear_trust_password,
+ sizeof(ucs2_trust_password), 0);
+
+ encode_pw_buffer((char *)pwbuf, ucs2_trust_password,
+ ucs2_pw_len);
+
+ /* Set password on machine account */
+
+ ZERO_STRUCT(ctr);
+ ZERO_STRUCT(p24);
+
+ init_sam_user_info24(&p24, (char *)pwbuf,24);
+
+ ctr.switch_value = 24;
+ ctr.info.id24 = &p24;
+
+ /* I don't think this is quite the right place for this
+ calculation. It should be moved somewhere where the credentials
+ are calculated. )-: */
+
+ mdfour(sess_key, cli->pwd.smb_nt_pwd, 16);
+
+ CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
+ sess_key, &ctr),
+ "error setting trust account password");
+
+ /* Why do we have to try to (re-)set the ACB to be the same as what
+ we passed in the samr_create_dom_user() call? When a NT
+ workstation is joined to a domain by an administrator the
+ acb_info is set to 0x80. For a normal user with "Add
+ workstations to the domain" rights the acb_info is 0x84. I'm
+ not sure whether it is supposed to make a difference or not. NT
+ seems to cope with either value so don't bomb out if the set
+ userinfo2 level 0x10 fails. -tpot */
+
+ ZERO_STRUCT(ctr);
+ ctr.switch_value = 0x10;
+ ctr.info.id10 = &p10;
+
+ init_sam_user_info10(&p10, acb_info);
+
+ /* Ignoring the return value is necessary for joining a domain
+ as a normal user with "Add workstation to domain" privilege. */
+
+ result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10,
+ sess_key, &ctr);
+
+ /* Now store the secret in the secrets database */
+
+ strupper(domain);
+
+ if (!secrets_store_domain_sid(domain, &domain_sid)) {
+ DEBUG(0, ("error storing domain sid for %s\n", domain));
+ goto done;
+ }
+
+ if (!secrets_store_machine_password(clear_trust_password)) {
+ DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain));
+ }
+
+ /* Now check the whole process from top-to-bottom */
+
+ cli_samr_close(cli, mem_ctx, &user_pol);
+
+ cli_nt_session_close(cli); /* Done with this pipe */
+
+ if (!cli_nt_session_open(cli, PIPE_NETLOGON)) {
+ DEBUG(0, ("Error connecting to NETLOGON pipe\n"));
+ goto done;
+ }
+
+ if (!secrets_fetch_trust_account_password(domain,
+ stored_md4_trust_password, NULL)) {
+ DEBUG(0, ("Could not reterive secrets we just stored!"));
+ goto done;
+ }
+
+ CHECK_RPC_ERR(new_cli_nt_setup_creds(cli,
+ (acb_info & ACB_SVRTRUST) ? SEC_CHAN_BDC : SEC_CHAN_WKSTA,
+ stored_md4_trust_password),
+ "error in domain join verification");
+
+ retval = 0; /* Success! */
+
+done:
+ /* Close down pipe - this will clean up open policy handles */
+
+ if (cli->nt_pipe_fnum)
+ cli_nt_session_close(cli);
+
+ /* Display success or failure */
+
+ if (retval != 0) {
+ trust_password_delete(domain);
+ fprintf(stderr,"Unable to join domain %s.\n",domain);
+ } else {
+ printf("Joined domain %s.\n",domain);
+ }
+
+ cli_shutdown(cli);
+
+ SAFE_FREE(clear_trust_password);
+
+ return retval;
+}
diff --git a/source3/utils/net_time.c b/source3/utils/net_time.c
new file mode 100644
index 0000000000..3f5532109c
--- /dev/null
+++ b/source3/utils/net_time.c
@@ -0,0 +1,185 @@
+/*
+ Samba Unix/Linux SMB client library
+ net time command
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+
+ 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 "../utils/net.h"
+
+
+/*
+ return the time on a server. This does not require any authentication
+*/
+static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
+{
+ struct nmb_name calling, called;
+ time_t ret = 0;
+ extern pstring global_myname;
+ struct cli_state *cli = NULL;
+
+ cli = cli_initialise(NULL);
+ if (!cli) goto done;
+
+ if (!cli_connect(cli, host, ip)) {
+ fprintf(stderr,"Can't contact server\n");
+ goto done;
+ }
+
+ make_nmb_name(&calling, global_myname, 0x0);
+ if (host) {
+ make_nmb_name(&called, host, 0x20);
+ } else {
+ make_nmb_name(&called, "*SMBSERVER", 0x20);
+ }
+
+ if (!cli_session_request(cli, &calling, &called)) {
+ fprintf(stderr,"Session request failed\n");
+ goto done;
+ }
+ if (!cli_negprot(cli)) {
+ fprintf(stderr,"Protocol negotiation failed\n");
+ goto done;
+ }
+
+ ret = cli->servertime;
+ if (zone) *zone = cli->serverzone;
+
+done:
+ if (cli) cli_shutdown(cli);
+ return ret;
+}
+
+/* find the servers time on the opt_host host */
+static time_t nettime(int *zone)
+{
+ extern BOOL opt_have_ip;
+ extern struct in_addr opt_dest_ip;
+ extern char *opt_host;
+ return cli_servertime(opt_host, opt_have_ip? &opt_dest_ip : NULL, zone);
+}
+
+/* return a time as a string ready to be passed to /bin/date */
+static char *systime(time_t t)
+{
+ static char s[100];
+ struct tm *tm;
+
+ tm = localtime(&t);
+
+ snprintf(s, sizeof(s), "%02d%02d%02d%02d%04d.%02d",
+ tm->tm_mon+1, tm->tm_mday, tm->tm_hour,
+ tm->tm_min, tm->tm_year + 1900, tm->tm_sec);
+ return s;
+}
+
+int net_time_usage(int argc, const char **argv)
+{
+ d_printf(
+"net time\n\tdisplays time on a server\n\n"\
+"net time system\n\tdisplays time on a server in a format ready for /bin/date\n\n"\
+"net time set\n\truns /bin/date with the time from the server\n\n"\
+"net time zone\n\tdisplays the timezone in hours from GMT on the remote computer\n\n"\
+"\n");
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+/* try to set the system clock using /bin/date */
+static int net_time_set(int argc, const char **argv)
+{
+ time_t t = nettime(NULL);
+ char *cmd;
+
+ if (t == 0) return -1;
+
+ /* yes, I know this is cheesy. Use "net time system" if you want to
+ roll your own. I'm putting this in as it works on a large number
+ of systems and the user has a choice in whether its used or not */
+ asprintf(&cmd, "/bin/date %s", systime(t));
+ system(cmd);
+ free(cmd);
+
+ return 0;
+}
+
+/* display the time on a remote box in a format ready for /bin/date */
+static int net_time_system(int argc, const char **argv)
+{
+ time_t t = nettime(NULL);
+
+ if (t == 0) return -1;
+
+ printf("%s\n", systime(t));
+
+ return 0;
+}
+
+/* display the time on a remote box in a format ready for /bin/date */
+static int net_time_zone(int argc, const char **argv)
+{
+ int zone = 0;
+ int hours, mins;
+ char zsign;
+ time_t t;
+
+ t = nettime(&zone);
+
+ if (t == 0) return -1;
+
+ zsign = (zone > 0) ? '-' : '+';
+ if (zone < 0) zone = -zone;
+
+ zone /= 60;
+ hours = zone / 60;
+ mins = zone % 60;
+
+ printf("%c%02d%02d\n", zsign, hours, mins);
+
+ return 0;
+}
+
+/* display or set the time on a host */
+int net_time(int argc, const char **argv)
+{
+ time_t t;
+ extern BOOL opt_have_ip;
+ extern struct in_addr opt_dest_ip;
+ extern char *opt_host;
+ struct functable func[] = {
+ {"SYSTEM", net_time_system},
+ {"SET", net_time_set},
+ {"ZONE", net_time_zone},
+ {NULL, NULL}
+ };
+
+ if (!opt_host && !opt_have_ip) {
+ d_printf("You must specify a hostname or IP\n");
+ net_time_usage(argc,argv);
+ return -1;
+ }
+
+ if (argc != 0) {
+ return net_run_function(argc, argv, func, net_time_usage);
+ }
+
+ /* default - print the time */
+ t = cli_servertime(opt_host, opt_have_ip? &opt_dest_ip : NULL, NULL);
+ if (t == 0) return -1;
+
+ d_printf("%s", ctime(&t));
+ return 0;
+}
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index aa43173332..9549d16d04 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -1,8 +1,7 @@
/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
NBT client - used to lookup netbios names
- Copyright (C) Andrew Tridgell 1994-1995
+ Copyright (C) Andrew Tridgell 1994-1998
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
@@ -20,44 +19,35 @@
*/
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
+#define NO_SYSLOG
#include "includes.h"
-#include "nameserv.h"
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-
-extern struct in_addr bcast_ip;
-extern pstring myhostname;
+extern BOOL AllowDebugChange;
+static BOOL use_bcast = True;
static BOOL got_bcast = False;
-
-int ServerFD= -1;
+static struct in_addr bcast_addr;
+static BOOL recursion_desired = False;
+static BOOL translate_addresses = False;
+static int ServerFD= -1;
+static int RootPort = False;
+static BOOL find_status=False;
/****************************************************************************
open the socket communication
**************************************************************************/
static BOOL open_sockets(void)
{
- struct hostent *hp;
-
- /* get host info */
- if ((hp = Get_Hostbyname(myhostname)) == 0)
- {
- DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
- return False;
- }
-
- ServerFD = open_socket_in(SOCK_DGRAM, 0,3);
+ ServerFD = open_socket_in( SOCK_DGRAM,
+ (RootPort ? 137 : 0),
+ (RootPort ? 0 : 3),
+ interpret_addr(lp_socket_address()), True );
if (ServerFD == -1)
return(False);
- set_socket_options(ServerFD,"SO_BROADCAST");
+ set_socket_options( ServerFD, "SO_BROADCAST" );
DEBUG(3, ("Socket opened.\n"));
return True;
@@ -65,43 +55,128 @@ static BOOL open_sockets(void)
/****************************************************************************
- initialise connect, service and file structs
+usage on the program
****************************************************************************/
-static BOOL init_structs(void )
+static void usage(void)
{
- struct in_addr myip;
-
- if (!get_myname(myhostname,&myip))
- return(False);
-
- /* Read the broadcast address from the interface */
- {
- struct in_addr ip0,ip2;
-
- ip0 = myip;
-
- if (!got_bcast) {
- get_broadcast(&ip0,&bcast_ip,&ip2);
+ d_printf("Usage: nmblookup [-M] [-B bcast address] [-d debuglevel] name\n");
+ d_printf("Version %s\n",VERSION);
+ d_printf("\t-d debuglevel set the debuglevel\n");
+ d_printf("\t-B broadcast address the address to use for broadcasts\n");
+ d_printf("\t-U unicast address the address to use for unicast\n");
+ d_printf("\t-M searches for a master browser\n");
+ d_printf("\t-R set recursion desired in packet\n");
+ d_printf("\t-S lookup node status as well\n");
+ d_printf("\t-T translate IP addresses into names\n");
+ d_printf("\t-r Use root port 137 (Win95 only replies to this)\n");
+ d_printf("\t-A Do a node status on <name> as an IP Address\n");
+ d_printf("\t-i NetBIOS scope Use the given NetBIOS scope for name queries\n");
+ d_printf("\t-s smb.conf file Use the given path to the smb.conf file\n");
+ d_printf("\t-h Print this help message.\n");
+ d_printf("\n If you specify -M and name is \"-\", nmblookup looks up __MSBROWSE__<01>\n");
+ d_printf("\n");
+}
- DEBUG(2,("Using broadcast %s\n",inet_ntoa(bcast_ip)));
- }
- }
+/****************************************************************************
+turn a node status flags field into a string
+****************************************************************************/
+static char *node_status_flags(unsigned char flags)
+{
+ static fstring ret;
+ fstrcpy(ret,"");
+
+ fstrcat(ret, (flags & 0x80) ? "<GROUP> " : " ");
+ if ((flags & 0x60) == 0x00) fstrcat(ret,"B ");
+ if ((flags & 0x60) == 0x20) fstrcat(ret,"P ");
+ if ((flags & 0x60) == 0x40) fstrcat(ret,"M ");
+ if ((flags & 0x60) == 0x60) fstrcat(ret,"H ");
+ if (flags & 0x10) fstrcat(ret,"<DEREGISTERING> ");
+ if (flags & 0x08) fstrcat(ret,"<CONFLICT> ");
+ if (flags & 0x04) fstrcat(ret,"<ACTIVE> ");
+ if (flags & 0x02) fstrcat(ret,"<PERMANENT> ");
+
+ return ret;
+}
- return True;
+/****************************************************************************
+do a node status query
+****************************************************************************/
+static void do_node_status(int fd, char *name, int type, struct in_addr ip)
+{
+ struct nmb_name nname;
+ int count, i, j;
+ struct node_status *status;
+ fstring cleanname;
+
+ d_printf("Looking up status of %s\n",inet_ntoa(ip));
+ make_nmb_name(&nname, name, type);
+ status = node_status_query(fd,&nname,ip, &count);
+ if (status) {
+ for (i=0;i<count;i++) {
+ fstrcpy(cleanname, status[i].name);
+ for (j=0;cleanname[j];j++) {
+ if (!isprint((int)cleanname[j])) cleanname[j] = '.';
+ }
+ d_printf("\t%-15s <%02x> - %s\n",
+ cleanname,status[i].type,
+ node_status_flags(status[i].flags));
+ }
+ SAFE_FREE(status);
+ }
+ d_printf("\n");
}
+
/****************************************************************************
-usage on the program
+send out one query
****************************************************************************/
-static void usage(void)
+static BOOL query_one(char *lookup, unsigned int lookup_type)
{
- printf("Usage: nmblookup [-M] [-B bcast address] [-d debuglevel] name\n");
- printf("Version %s\n",VERSION);
- printf("\t-d debuglevel set the debuglevel\n");
- printf("\t-B broadcast address the address to use for broadcasts\n");
- printf("\t-M searches for a master browser\n");
- printf("\t-S lookup node status as well\n");
- printf("\n");
+ int j, count;
+ struct in_addr *ip_list=NULL;
+
+ if (got_bcast) {
+ d_printf("querying %s on %s\n", lookup, inet_ntoa(bcast_addr));
+ ip_list = name_query(ServerFD,lookup,lookup_type,use_bcast,
+ use_bcast?True:recursion_desired,
+ bcast_addr,&count);
+ } else {
+ struct in_addr *bcast;
+ for (j=iface_count() - 1;
+ !ip_list && j >= 0;
+ j--) {
+ bcast = iface_n_bcast(j);
+ d_printf("querying %s on %s\n",
+ lookup, inet_ntoa(*bcast));
+ ip_list = name_query(ServerFD,lookup,lookup_type,
+ use_bcast,
+ use_bcast?True:recursion_desired,
+ *bcast,&count);
+ }
+ }
+
+ if (!ip_list) return False;
+
+ for (j=0;j<count;j++) {
+ if (translate_addresses) {
+ struct hostent *host = gethostbyaddr((char *)&ip_list[j], sizeof(ip_list[j]), AF_INET);
+ if (host) {
+ d_printf("%s, ", host -> h_name);
+ }
+ }
+ d_printf("%s %s<%02x>\n",inet_ntoa(ip_list[j]),lookup, lookup_type);
+ }
+
+ /* We can only do find_status if the ip address returned
+ was valid - ie. name_query returned true.
+ */
+ if (find_status) {
+ do_node_status(ServerFD, lookup, lookup_type, ip_list[0]);
+ }
+
+ safe_free(ip_list);
+
+ return (ip_list != NULL);
}
@@ -111,50 +186,71 @@ static void usage(void)
int main(int argc,char *argv[])
{
int opt;
- unsigned int lookup_type = 0x20;
+ unsigned int lookup_type = 0x0;
pstring lookup;
extern int optind;
extern char *optarg;
BOOL find_master=False;
- BOOL find_status=False;
int i;
-
+ BOOL lookup_by_ip = False;
+ int commandline_debuglevel = -2;
+
DEBUGLEVEL = 1;
- *lookup = 0;
+ /* Prevent smb.conf setting from overridding */
+ AllowDebugChange = False;
- TimeInit();
+ *lookup = 0;
setup_logging(argv[0],True);
- charset_initialise();
-
- while ((opt = getopt(argc, argv, "p:d:B:i:SMh")) != EOF)
+ while ((opt = getopt(argc, argv, "d:B:U:i:s:SMrhART")) != EOF)
switch (opt)
{
case 'B':
- {
- unsigned long a = interpret_addr(optarg);
- putip((char *)&bcast_ip,(char *)&a);
- got_bcast = True;
- }
+ bcast_addr = *interpret_addr2(optarg);
+ got_bcast = True;
+ use_bcast = True;
break;
- case 'i':
- strcpy(scope,optarg);
- strupper(scope);
+ case 'U':
+ bcast_addr = *interpret_addr2(optarg);
+ got_bcast = True;
+ use_bcast = False;
+ break;
+ case 'T':
+ translate_addresses = !translate_addresses;
break;
+ case 'i':
+ {
+ extern pstring global_scope;
+ pstrcpy(global_scope,optarg);
+ strupper(global_scope);
+ }
+ break;
case 'M':
find_master = True;
break;
case 'S':
find_status = True;
break;
+ case 'R':
+ recursion_desired = True;
+ break;
case 'd':
- DEBUGLEVEL = atoi(optarg);
+ commandline_debuglevel = DEBUGLEVEL = atoi(optarg);
+ break;
+ case 's':
+ pstrcpy(dyn_CONFIGFILE, optarg);
break;
+ case 'r':
+ RootPort = True;
+ break;
case 'h':
usage();
exit(0);
break;
+ case 'A':
+ lookup_by_ip = True;
+ break;
default:
usage();
exit(1);
@@ -165,53 +261,58 @@ int main(int argc,char *argv[])
exit(1);
}
- init_structs();
- if (!open_sockets()) return(1);
+ if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
+ }
- DEBUG(1,("Sending queries to %s\n",inet_ntoa(bcast_ip)));
+ /*
+ * Ensure we reset DEBUGLEVEL if someone specified it
+ * on the command line.
+ */
+ if(commandline_debuglevel != -2)
+ DEBUGLEVEL = commandline_debuglevel;
+
+ load_interfaces();
+ if (!open_sockets()) return(1);
for (i=optind;i<argc;i++)
- {
- BOOL bcast = True;
- int retries = 2;
+ {
char *p;
struct in_addr ip;
- strcpy(lookup,argv[i]);
+ fstrcpy(lookup,argv[i]);
+
+ if(lookup_by_ip)
+ {
+ fstrcpy(lookup,"*");
+ ip = *interpret_addr2(argv[i]);
+ do_node_status(ServerFD, lookup, lookup_type, ip);
+ continue;
+ }
if (find_master) {
if (*lookup == '-') {
- strcpy(lookup,"\01\02__MSBROWSE__\02");
+ fstrcpy(lookup,"\01\02__MSBROWSE__\02");
lookup_type = 1;
} else {
lookup_type = 0x1d;
}
}
- p = strchr(lookup,'#');
-
+ p = strchr_m(lookup,'#');
if (p) {
- *p = 0;
- sscanf(p+1,"%x",&lookup_type);
- bcast = False;
- retries = 1;
+ *p = '\0';
+ sscanf(++p,"%x",&lookup_type);
}
- if (name_query(ServerFD,lookup,lookup_type,bcast,True,
- bcast_ip,&ip,NULL))
- {
- printf("%s %s\n",inet_ntoa(ip),lookup);
- if (find_status)
- {
- printf("Looking up status of %s\n",inet_ntoa(ip));
- name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL);
- printf("\n");
- }
- } else {
- printf("couldn't find name %s\n",lookup);
+ if (!query_one(lookup, lookup_type)) {
+ d_printf( "name_query failed to find name %s", lookup );
+ if( 0 != lookup_type )
+ d_printf( "#%02x", lookup_type );
+ d_printf( "\n" );
}
- }
-
+ }
+
return(0);
}
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
new file mode 100644
index 0000000000..1fb1f2355b
--- /dev/null
+++ b/source3/utils/pdbedit.c
@@ -0,0 +1,692 @@
+/*
+ Unix SMB/CIFS implementation.
+ passdb editing frontend
+
+ Copyright (C) Simo Sorce 2000
+ Copyright (C) Andrew Bartlett 2001
+
+ 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"
+
+extern pstring global_myname;
+extern BOOL AllowDebugChange;
+
+/*
+ * Next two lines needed for SunOS and don't
+ * hurt anything else...
+ */
+extern char *optarg;
+extern int optind;
+
+/*********************************************************
+ Print command usage on stderr and die.
+**********************************************************/
+static void usage(void)
+{
+ if (getuid() == 0) {
+ printf("pdbedit options\n");
+ } else {
+ printf("You need to be root to use this tool!\n");
+ }
+ printf("(actually to add a user you need to use smbpasswd)\n");
+ printf("options:\n");
+ printf(" -l list usernames\n");
+ printf(" -v verbose output\n");
+ printf(" -w smbpasswd file style\n");
+ printf(" -u username print user's info\n");
+ printf(" -f fullname set Full Name\n");
+ printf(" -h homedir set home directory\n");
+ printf(" -d drive set home dir drive\n");
+ printf(" -s script set logon script\n");
+ printf(" -p profile set profile path\n");
+ printf(" -a create new account\n");
+ printf(" -m it is a machine trust\n");
+ printf(" -x delete this user\n");
+ printf(" -i file import account from file (smbpasswd style)\n");
+ printf(" -D debuglevel set DEBUGELEVEL (default = 1)\n");
+ exit(1);
+}
+
+/*********************************************************
+ Print info from sam structure
+**********************************************************/
+
+static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
+{
+ uid_t uid;
+ gid_t gid;
+
+ /* TODO: chaeck if entry is a user or a workstation */
+ if (!sam_pwent) return -1;
+
+ if (verbosity) {
+ printf ("username: %s\n", pdb_get_username(sam_pwent));
+ if (IS_SAM_UNIX_USER(sam_pwent)) {
+ uid = pdb_get_uid(sam_pwent);
+ gid = pdb_get_gid(sam_pwent);
+ printf ("user ID/Group: %d/%d\n", uid, gid);
+ }
+ printf ("user RID/GRID: %u/%u\n", (unsigned int)pdb_get_user_rid(sam_pwent),
+ (unsigned int)pdb_get_group_rid(sam_pwent));
+ printf ("Full Name: %s\n", pdb_get_fullname(sam_pwent));
+ printf ("Home Directory: %s\n", pdb_get_homedir(sam_pwent));
+ printf ("HomeDir Drive: %s\n", pdb_get_dirdrive(sam_pwent));
+ printf ("Logon Script: %s\n", pdb_get_logon_script(sam_pwent));
+ printf ("Profile Path: %s\n", pdb_get_profile_path(sam_pwent));
+ } else if (smbpwdstyle) {
+ if (IS_SAM_UNIX_USER(sam_pwent)) {
+ char lm_passwd[33];
+ char nt_passwd[33];
+
+ uid = pdb_get_uid(sam_pwent);
+ pdb_sethexpwd(lm_passwd,
+ pdb_get_lanman_passwd(sam_pwent),
+ pdb_get_acct_ctrl(sam_pwent));
+ pdb_sethexpwd(nt_passwd,
+ pdb_get_nt_passwd(sam_pwent),
+ pdb_get_acct_ctrl(sam_pwent));
+
+ printf("%s:%d:%s:%s:%s:LCT-%08X:\n",
+ pdb_get_username(sam_pwent),
+ uid,
+ lm_passwd,
+ nt_passwd,
+ pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN),
+ (uint32)pdb_get_pass_last_set_time(sam_pwent));
+ } else {
+ fprintf(stderr, "Can't output in smbpasswd format, no uid on this record.\n");
+ }
+ } else {
+ if (IS_SAM_UNIX_USER(sam_pwent)) {
+ printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), pdb_get_uid(sam_pwent),
+ pdb_get_fullname(sam_pwent));
+ } else {
+ printf ("%s:(null):%s\n", pdb_get_username(sam_pwent), pdb_get_fullname(sam_pwent));
+ }
+ }
+
+ return 0;
+}
+
+/*********************************************************
+ Get an Print User Info
+**********************************************************/
+
+static int print_user_info (char *username, BOOL verbosity, BOOL smbpwdstyle)
+{
+ SAM_ACCOUNT *sam_pwent=NULL;
+ BOOL ret;
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
+ return -1;
+ }
+
+ ret = pdb_getsampwnam (sam_pwent, username);
+
+ if (ret==False) {
+ fprintf (stderr, "Username not found!\n");
+ pdb_free_sam(&sam_pwent);
+ return -1;
+ }
+
+ ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
+ pdb_free_sam(&sam_pwent);
+
+ return ret;
+}
+
+/*********************************************************
+ List Users
+**********************************************************/
+static int print_users_list (BOOL verbosity, BOOL smbpwdstyle)
+{
+ SAM_ACCOUNT *sam_pwent=NULL;
+ BOOL check, ret;
+
+ errno = 0; /* testing --simo */
+ check = pdb_setsampwent(False);
+ if (check && errno == ENOENT) {
+ fprintf (stderr,"Password database not found!\n");
+ exit(1);
+ }
+
+ check = True;
+ if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1;
+
+ while (check && (ret = pdb_getsampwent (sam_pwent))) {
+ if (verbosity)
+ printf ("---------------\n");
+ print_sam_info (sam_pwent, verbosity, smbpwdstyle);
+ pdb_free_sam(&sam_pwent);
+ check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent));
+ }
+ if (check) pdb_free_sam(&sam_pwent);
+
+ pdb_endsampwent();
+ return 0;
+}
+
+/*********************************************************
+ Set User Info
+**********************************************************/
+
+static int set_user_info (char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
+{
+ SAM_ACCOUNT *sam_pwent=NULL;
+ BOOL ret;
+
+ pdb_init_sam(&sam_pwent);
+
+ ret = pdb_getsampwnam (sam_pwent, username);
+ if (ret==False) {
+ fprintf (stderr, "Username not found!\n");
+ pdb_free_sam(&sam_pwent);
+ return -1;
+ }
+
+ if (fullname)
+ pdb_set_fullname(sam_pwent, fullname);
+ if (homedir)
+ pdb_set_homedir(sam_pwent, homedir, True);
+ if (drive)
+ pdb_set_dir_drive(sam_pwent,drive, True);
+ if (script)
+ pdb_set_logon_script(sam_pwent, script, True);
+ if (profile)
+ pdb_set_profile_path (sam_pwent, profile, True);
+
+ if (pdb_update_sam_account (sam_pwent))
+ print_user_info (username, True, False);
+ else {
+ fprintf (stderr, "Unable to modify entry!\n");
+ pdb_free_sam(&sam_pwent);
+ return -1;
+ }
+ pdb_free_sam(&sam_pwent);
+ return 0;
+}
+
+/*********************************************************
+ Add New User
+**********************************************************/
+static int new_user (char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
+{
+ SAM_ACCOUNT *sam_pwent=NULL;
+ struct passwd *pwd = NULL;
+ char *password1, *password2;
+
+ ZERO_STRUCT(sam_pwent);
+
+ if ((pwd = getpwnam_alloc(username))) {
+ pdb_init_sam_pw (&sam_pwent, pwd);
+ passwd_free(&pwd);
+ } else {
+ fprintf (stderr, "WARNING: user %s does not exist in system passwd\n", username);
+ pdb_init_sam(&sam_pwent);
+ if (!pdb_set_username(sam_pwent, username)) {
+ return False;
+ }
+ }
+
+ password1 = getpass("new password:");
+ password2 = getpass("retype new password:");
+ if (strcmp (password1, password2)) {
+ fprintf (stderr, "Passwords does not match!\n");
+ pdb_free_sam (&sam_pwent);
+ return -1;
+ }
+
+ pdb_set_plaintext_passwd(sam_pwent, password1);
+
+ if (fullname)
+ pdb_set_fullname(sam_pwent, fullname);
+ if (homedir)
+ pdb_set_homedir (sam_pwent, homedir, True);
+ if (drive)
+ pdb_set_dir_drive (sam_pwent, drive, True);
+ if (script)
+ pdb_set_logon_script(sam_pwent, script, True);
+ if (profile)
+ pdb_set_profile_path (sam_pwent, profile, True);
+
+ pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL);
+
+ if (pdb_add_sam_account (sam_pwent)) {
+ print_user_info (username, True, False);
+ } else {
+ fprintf (stderr, "Unable to add user! (does it alredy exist?)\n");
+ pdb_free_sam (&sam_pwent);
+ return -1;
+ }
+ pdb_free_sam (&sam_pwent);
+ return 0;
+}
+
+/*********************************************************
+ Add New Machine
+**********************************************************/
+
+static int new_machine (char *machinename)
+{
+ SAM_ACCOUNT *sam_pwent=NULL;
+ char name[16];
+ char *password = NULL;
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
+ return -1;
+ }
+
+ if (machinename[strlen (machinename) -1] == '$')
+ machinename[strlen (machinename) -1] = '\0';
+
+ safe_strcpy (name, machinename, 16);
+ safe_strcat (name, "$", 16);
+
+ string_set (&password, machinename);
+ strlower_m(password);
+
+ pdb_set_plaintext_passwd (sam_pwent, password);
+
+ pdb_set_username (sam_pwent, name);
+
+ pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST);
+
+ pdb_set_group_rid(sam_pwent, DOMAIN_GROUP_RID_COMPUTERS);
+
+ if (pdb_add_sam_account (sam_pwent)) {
+ print_user_info (name, True, False);
+ } else {
+ fprintf (stderr, "Unable to add machine! (does it already exist?)\n");
+ pdb_free_sam (&sam_pwent);
+ return -1;
+ }
+ pdb_free_sam (&sam_pwent);
+ return 0;
+}
+
+/*********************************************************
+ Delete user entry
+**********************************************************/
+
+static int delete_user_entry (char *username)
+{
+ SAM_ACCOUNT *samaccount = NULL;
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
+ return -1;
+ }
+
+ if (!pdb_getsampwnam(samaccount, username)) {
+ fprintf (stderr, "user %s does not exist in the passdb\n", username);
+ return -1;
+ }
+
+ return pdb_delete_sam_account (samaccount);
+}
+
+/*********************************************************
+ Delete machine entry
+**********************************************************/
+
+static int delete_machine_entry (char *machinename)
+{
+ char name[16];
+ SAM_ACCOUNT *samaccount = NULL;
+
+ safe_strcpy (name, machinename, 16);
+ if (name[strlen(name)] != '$')
+ safe_strcat (name, "$", 16);
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
+ return -1;
+ }
+
+ if (!pdb_getsampwnam(samaccount, name)) {
+ fprintf (stderr, "user %s does not exist in the passdb\n", name);
+ return -1;
+ }
+
+ return pdb_delete_sam_account (samaccount);
+}
+
+/*********************************************************
+ Import smbpasswd style file
+**********************************************************/
+
+static int import_users (char *filename)
+{
+ FILE *fp = NULL;
+ SAM_ACCOUNT *sam_pwent = NULL;
+ static pstring user_name;
+ static unsigned char smbpwd[16];
+ static unsigned char smbntpwd[16];
+ char linebuf[256];
+ size_t linebuf_len;
+ unsigned char c;
+ unsigned char *p;
+ long uidval;
+ int line = 0;
+ int good = 0;
+ struct passwd *pwd;
+
+ if((fp = sys_fopen(filename, "rb")) == NULL) {
+ fprintf (stderr, "%s\n", strerror (ferror (fp)));
+ return -1;
+ }
+
+ while (!feof(fp)) {
+ /*Get a new line*/
+ linebuf[0] = '\0';
+ fgets(linebuf, 256, fp);
+ if (ferror(fp)) {
+ fprintf (stderr, "%s\n", strerror (ferror (fp)));
+ return -1;
+ }
+ if ((linebuf_len = strlen(linebuf)) == 0) {
+ line++;
+ continue;
+ }
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n') break;
+ }
+ } else
+ linebuf[linebuf_len - 1] = '\0';
+ linebuf[linebuf_len] = '\0';
+ if ((linebuf[0] == 0) && feof(fp)) {
+ /*end of file!!*/
+ return 0;
+ }
+ line++;
+ if (linebuf[0] == '#' || linebuf[0] == '\0')
+ continue;
+
+ /* Get user name */
+ p = (unsigned char *) strchr_m(linebuf, ':');
+ if (p == NULL) {
+ fprintf (stderr, "Error: malformed password entry at line %d !!\n", line);
+ continue;
+ }
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+
+ /* Get smb uid. */
+ p++;
+ if(*p == '-') {
+ fprintf (stderr, "Error: negative uid at line %d\n", line);
+ continue;
+ }
+ if (!isdigit(*p)) {
+ fprintf (stderr, "Error: malformed password entry at line %d (uid not number)\n", line);
+ continue;
+ }
+ uidval = atoi((char *) p);
+ while (*p && isdigit(*p)) p++;
+ if (*p != ':') {
+ fprintf (stderr, "Error: malformed password entry at line %d (no : after uid)\n", line);
+ continue;
+ }
+ if(!(pwd = sys_getpwnam(user_name))) {
+ fprintf(stderr, "User %s does not \
+exist in system password file (usually /etc/passwd). Cannot add \
+account without a valid local system user.\n", user_name);
+ return False;
+ }
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pwent, pwd))) {
+ fprintf(stderr, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
+ return False;
+ }
+
+ /* Get passwords */
+ p++;
+ if (*p == '*' || *p == 'X') {
+ /* Password deliberately invalid */
+ fprintf (stderr, "Warning: entry invalidated for user %s\n", user_name);
+ pdb_set_lanman_passwd(sam_pwent, NULL);
+ pdb_set_nt_passwd(sam_pwent,NULL);
+ pdb_set_acct_ctrl(sam_pwent, pdb_get_acct_ctrl(sam_pwent) | ACB_DISABLED);
+ } else {
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ fprintf (stderr, "Error: malformed password entry at line %d (password too short)\n",line);
+ pdb_free_sam (&sam_pwent);
+ continue;
+ }
+ if (p[32] != ':') {
+ fprintf (stderr, "Error: malformed password entry at line %d (no terminating :)\n",line);
+ pdb_free_sam (&sam_pwent);
+ continue;
+ }
+ if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
+ pdb_set_lanman_passwd(sam_pwent, NULL);
+ pdb_set_acct_ctrl(sam_pwent, pdb_get_acct_ctrl(sam_pwent) | ACB_PWNOTREQ);
+ } else {
+ if (!pdb_gethexpwd((char *)p, smbpwd)) {
+ fprintf (stderr, "Error: malformed Lanman password entry at line %d (non hex chars)\n", line);
+ pdb_free_sam (&sam_pwent);
+ continue;
+ }
+ pdb_set_lanman_passwd(sam_pwent, smbpwd);
+ }
+ /* NT password */
+ p += 33;
+ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
+ if (*p != '*' && *p != 'X') {
+ if (pdb_gethexpwd((char *)p,smbntpwd)) {
+ pdb_set_nt_passwd(sam_pwent, smbntpwd);
+ }
+ }
+ p += 33;
+ }
+ }
+
+ /* Get ACCT_CTRL field if any */
+ if (*p == '[') {
+ uint16 acct_ctrl;
+ unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
+
+ acct_ctrl = pdb_decode_acct_ctrl((char*)p);
+ if (acct_ctrl)
+ acct_ctrl = ACB_NORMAL;
+
+ pdb_set_acct_ctrl(sam_pwent, acct_ctrl);
+
+ /* Get last change time */
+ if(end_p)
+ p = end_p + 1;
+ if(*p == ':') {
+ p++;
+ if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
+ int i;
+
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i])) break;
+ }
+ if(i == 8) {
+ pdb_set_pass_last_set_time (sam_pwent, (time_t)strtol((char *)p, NULL, 16));
+ }
+ }
+ }
+ }
+
+ /* Now ADD the entry */
+ if (!(pdb_add_sam_account (sam_pwent))) {
+ fprintf (stderr, "Unable to add user entry!\n");
+ pdb_free_sam (&sam_pwent);
+ continue;
+ }
+ printf ("%s imported!\n", user_name);
+ good++;
+ pdb_free_sam (&sam_pwent);
+ }
+ printf ("%d lines read.\n%d entryes imported\n", line, good);
+ return 0;
+}
+
+/*********************************************************
+ Start here.
+**********************************************************/
+
+int main (int argc, char **argv)
+{
+ int ch;
+ BOOL list_users = False;
+ BOOL verbose = False;
+ BOOL spstyle = False;
+ BOOL setparms = False;
+ BOOL machine = False;
+ BOOL add_user = False;
+ BOOL delete_user = False;
+ BOOL import = False;
+ char *user_name = NULL;
+ char *full_name = NULL;
+ char *home_dir = NULL;
+ char *home_drive = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *smbpasswd = NULL;
+
+ setup_logging("pdbedit", True);
+
+ if (argc < 2) {
+ usage();
+ return 0;
+ }
+
+ DEBUGLEVEL = 1;
+ AllowDebugChange = False;
+
+ if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n",
+ dyn_CONFIGFILE);
+ exit(1);
+ }
+
+ if(!initialize_password_db(True)) {
+ fprintf(stderr, "Can't setup password database vectors.\n");
+ exit(1);
+ }
+
+ while ((ch = getopt(argc, argv, "ad:f:h:i:lmp:s:u:vwxD:")) != EOF) {
+ switch(ch) {
+ case 'a':
+ add_user = True;
+ break;
+ case 'm':
+ machine = True;
+ break;
+ case 'l':
+ list_users = True;
+ break;
+ case 'v':
+ verbose = True;
+ break;
+ case 'w':
+ spstyle = True;
+ break;
+ case 'u':
+ user_name = optarg;
+ break;
+ case 'f':
+ setparms = True;
+ full_name = optarg;
+ break;
+ case 'h':
+ setparms = True;
+ home_dir = optarg;
+ break;
+ case 'd':
+ setparms = True;
+ home_drive = optarg;
+ break;
+ case 's':
+ setparms = True;
+ logon_script = optarg;
+ break;
+ case 'p':
+ setparms = True;
+ profile_path = optarg;
+ break;
+ case 'x':
+ delete_user = True;
+ break;
+ case 'i':
+ import = True;
+ smbpasswd = optarg;
+ break;
+ case 'D':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+ if (((add_user?1:0) + (delete_user?1:0) + (list_users?1:0) + (import?1:0) + (setparms?1:0)) > 1) {
+ fprintf (stderr, "Incompatible options on command line!\n");
+ usage();
+ exit(1);
+ }
+
+ if (add_user) {
+ if (!user_name) {
+ fprintf (stderr, "Username not specified! (use -u option)\n");
+ return -1;
+ }
+ if (machine)
+ return new_machine (user_name);
+ else
+ return new_user (user_name, full_name, home_dir, home_drive, logon_script, profile_path);
+ }
+
+ if (delete_user) {
+ if (!user_name) {
+ fprintf (stderr, "Username not specified! (use -u option)\n");
+ return -1;
+ }
+ if (machine)
+ return delete_machine_entry (user_name);
+ else
+ return delete_user_entry (user_name);
+ }
+
+ if (user_name) {
+ if (setparms)
+ set_user_info ( user_name, full_name,
+ home_dir,
+ home_drive,
+ logon_script,
+ profile_path);
+ else
+ return print_user_info (user_name, verbose, spstyle);
+
+ return 0;
+ }
+
+
+ if (list_users)
+ return print_users_list (verbose, spstyle);
+
+ if (import)
+ return import_users (smbpasswd);
+
+ usage();
+
+ return 0;
+}
diff --git a/source3/utils/rpccheck.c b/source3/utils/rpccheck.c
new file mode 100644
index 0000000000..ab7286f8be
--- /dev/null
+++ b/source3/utils/rpccheck.c
@@ -0,0 +1,62 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Jean François Micouleau 2001
+
+ 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"
+
+main()
+{
+ char filter[]="0123456789ABCDEF";
+
+ char s[128];
+ char d=0;
+ int x=0;
+ prs_struct ps;
+ TALLOC_CTX *ctx;
+
+ /* change that struct */
+ SAMR_R_QUERY_USERINFO rpc_stub;
+
+ ZERO_STRUCT(rpc_stub);
+
+ setup_logging("", True);
+ DEBUGLEVEL=10;
+
+ ctx=talloc_init();
+ if (!ctx) exit(1);
+
+ prs_init(&ps, 1600, 4, ctx, MARSHALL);
+
+ while (scanf("%s", s)!=-1) {
+ if (strlen(s)==2 && strchr_m(filter, *s)!=NULL && strchr_m(filter, *(s+1))!=NULL) {
+ d=strtol(s, NULL, 16);
+ if(!prs_append_data(&ps, &d, 1))
+ printf("error while reading data\n");
+ }
+ }
+
+ prs_switch_type(&ps, UNMARSHALL);
+ prs_set_offset(&ps, 0);
+
+ /* change that call */
+ if(!samr_io_r_query_userinfo("", &rpc_stub, &ps, 0))
+ printf("error while UNMARSHALLING the data\n");
+
+ printf("\n");
+}
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
new file mode 100644
index 0000000000..8c0b2a4a72
--- /dev/null
+++ b/source3/utils/smbcacls.c
@@ -0,0 +1,964 @@
+/*
+ Unix SMB/CIFS implementation.
+ ACL get/set utility
+
+ Copyright (C) Andrew Tridgell 2000
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jeremy Allison 2000
+
+ 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"
+
+static fstring password;
+static pstring username;
+static pstring owner_username;
+static fstring server;
+static int got_pass;
+static int test_args;
+TALLOC_CTX *ctx;
+
+#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
+#define CREATE_ACCESS_WRITE (WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS)
+
+/* numeric is set when the user wants numeric SIDs and ACEs rather
+ than going via LSA calls to resolve them */
+static int numeric;
+
+enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
+enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP};
+enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
+
+struct perm_value {
+ char *perm;
+ uint32 mask;
+};
+
+/* These values discovered by inspection */
+
+static struct perm_value special_values[] = {
+ { "R", 0x00120089 },
+ { "W", 0x00120116 },
+ { "X", 0x001200a0 },
+ { "D", 0x00010000 },
+ { "P", 0x00040000 },
+ { "O", 0x00080000 },
+ { NULL, 0 },
+};
+
+static struct perm_value standard_values[] = {
+ { "READ", 0x001200a9 },
+ { "CHANGE", 0x001301bf },
+ { "FULL", 0x001f01ff },
+ { NULL, 0 },
+};
+
+struct cli_state lsa_cli;
+POLICY_HND pol;
+struct ntuser_creds creds;
+BOOL got_policy_hnd;
+
+/* Open cli connection and policy handle */
+
+static BOOL cacls_open_policy_hnd(void)
+{
+ creds.pwd.null_pwd = 1;
+
+ /* Initialise cli LSA connection */
+
+ if (!lsa_cli.initialised &&
+ !cli_lsa_initialise(&lsa_cli, server, &creds)) {
+ return False;
+ }
+
+ /* Open policy handle */
+
+ if (!got_policy_hnd) {
+
+ /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
+ but NT sends 0x2000000 so we might as well do it too. */
+
+ if (!NT_STATUS_IS_OK(cli_lsa_open_policy(&lsa_cli, lsa_cli.mem_ctx, True,
+ GENERIC_EXECUTE_ACCESS, &pol))) {
+ return False;
+ }
+
+ got_policy_hnd = True;
+ }
+
+ return True;
+}
+
+/* convert a SID to a string, either numeric or username/group */
+static void SidToString(fstring str, DOM_SID *sid)
+{
+ char **domains = NULL;
+ char **names = NULL;
+ uint32 *types = NULL;
+ int num_names;
+
+ sid_to_string(str, sid);
+
+ if (numeric) return;
+
+ /* Ask LSA to convert the sid to a name */
+
+ if (!cacls_open_policy_hnd() ||
+ !NT_STATUS_IS_OK(cli_lsa_lookup_sids(&lsa_cli, lsa_cli.mem_ctx,
+ &pol, 1, sid, &domains, &names,
+ &types, &num_names)) ||
+ !domains || !domains[0] || !names || !names[0]) {
+ return;
+ }
+
+ /* Converted OK */
+
+ slprintf(str, sizeof(fstring) - 1, "%s%s%s",
+ domains[0], lp_winbind_separator(),
+ names[0]);
+
+}
+
+/* convert a string to a SID, either numeric or username/group */
+static BOOL StringToSid(DOM_SID *sid, const char *str)
+{
+ uint32 *types = NULL;
+ DOM_SID *sids = NULL;
+ int num_sids;
+ BOOL result = True;
+
+ if (strncmp(str, "S-", 2) == 0) {
+ return string_to_sid(sid, str);
+ }
+
+ if (!cacls_open_policy_hnd() ||
+ !NT_STATUS_IS_OK(cli_lsa_lookup_names(&lsa_cli, lsa_cli.mem_ctx, &pol, 1,
+ &str,
+ &sids, &types, &num_sids))) {
+ result = False;
+ goto done;
+ }
+
+ sid_copy(sid, &sids[0]);
+
+ done:
+
+ return result;
+}
+
+
+/* print an ACE on a FILE, using either numeric or ascii representation */
+static void print_ace(FILE *f, SEC_ACE *ace)
+{
+ struct perm_value *v;
+ fstring sidstr;
+ int do_print = 0;
+ uint32 got_mask;
+
+ SidToString(sidstr, &ace->trustee);
+
+ fprintf(f, "%s:", sidstr);
+
+ if (numeric) {
+ fprintf(f, "%d/%d/0x%08x",
+ ace->type, ace->flags, ace->info.mask);
+ return;
+ }
+
+ /* Ace type */
+
+ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
+ fprintf(f, "ALLOWED");
+ } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ fprintf(f, "DENIED");
+ } else {
+ fprintf(f, "%d", ace->type);
+ }
+
+ /* Not sure what flags can be set in a file ACL */
+
+ fprintf(f, "/%d/", ace->flags);
+
+ /* Standard permissions */
+
+ for (v = standard_values; v->perm; v++) {
+ if (ace->info.mask == v->mask) {
+ fprintf(f, "%s", v->perm);
+ return;
+ }
+ }
+
+ /* Special permissions. Print out a hex value if we have
+ leftover bits in the mask. */
+
+ got_mask = ace->info.mask;
+
+ again:
+ for (v = special_values; v->perm; v++) {
+ if ((ace->info.mask & v->mask) == v->mask) {
+ if (do_print) {
+ fprintf(f, "%s", v->perm);
+ }
+ got_mask &= ~v->mask;
+ }
+ }
+
+ if (!do_print) {
+ if (got_mask != 0) {
+ fprintf(f, "0x%08x", ace->info.mask);
+ } else {
+ do_print = 1;
+ goto again;
+ }
+ }
+}
+
+
+/* parse an ACE in the same format as print_ace() */
+static BOOL parse_ace(SEC_ACE *ace, char *str)
+{
+ char *p;
+ fstring tok;
+ unsigned atype, aflags, amask;
+ DOM_SID sid;
+ SEC_ACCESS mask;
+ struct perm_value *v;
+
+ ZERO_STRUCTP(ace);
+ p = strchr_m(str,':');
+ if (!p) return False;
+ *p = '\0';
+ p++;
+
+ /* Try to parse numeric form */
+
+ if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
+ StringToSid(&sid, str)) {
+ goto done;
+ }
+
+ /* Try to parse text form */
+
+ if (!StringToSid(&sid, str)) {
+ return False;
+ }
+
+ if (!next_token(&p, tok, "/", sizeof(fstring))) {
+ return False;
+ }
+
+ if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
+ atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
+ atype = SEC_ACE_TYPE_ACCESS_DENIED;
+ } else {
+ return False;
+ }
+
+ /* Only numeric form accepted for flags at present */
+
+ if (!(next_token(&p, tok, "/", sizeof(fstring)) &&
+ sscanf(tok, "%i", &aflags))) {
+ return False;
+ }
+
+ if (!next_token(&p, tok, "/", sizeof(fstring))) {
+ return False;
+ }
+
+ if (strncmp(tok, "0x", 2) == 0) {
+ if (sscanf(tok, "%i", &amask) != 1) {
+ return False;
+ }
+ goto done;
+ }
+
+ for (v = standard_values; v->perm; v++) {
+ if (strcmp(tok, v->perm) == 0) {
+ amask = v->mask;
+ goto done;
+ }
+ }
+
+ p = tok;
+
+ while(*p) {
+ BOOL found = False;
+
+ for (v = special_values; v->perm; v++) {
+ if (v->perm[0] == *p) {
+ amask |= v->mask;
+ found = True;
+ }
+ }
+
+ if (!found) return False;
+ p++;
+ }
+
+ if (*p) {
+ return False;
+ }
+
+ done:
+ mask.mask = amask;
+ init_sec_ace(ace, &sid, atype, mask, aflags);
+ return True;
+}
+
+/* add an ACE to a list of ACEs in a SEC_ACL */
+static BOOL add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
+{
+ SEC_ACL *new;
+ SEC_ACE *aces;
+ if (! *the_acl) {
+ (*the_acl) = make_sec_acl(ctx, 3, 1, ace);
+ return True;
+ }
+
+ aces = calloc(1+(*the_acl)->num_aces,sizeof(SEC_ACE));
+ memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE));
+ memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
+ new = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
+ SAFE_FREE(aces);
+ (*the_acl) = new;
+ return True;
+}
+
+/* parse a ascii version of a security descriptor */
+static SEC_DESC *sec_desc_parse(char *str)
+{
+ char *p = str;
+ fstring tok;
+ SEC_DESC *ret;
+ size_t sd_size;
+ DOM_SID *grp_sid=NULL, *owner_sid=NULL;
+ SEC_ACL *dacl=NULL;
+ int revision=1;
+
+ while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) {
+
+ if (strncmp(tok,"REVISION:", 9) == 0) {
+ revision = strtol(tok+9, NULL, 16);
+ continue;
+ }
+
+ if (strncmp(tok,"OWNER:", 6) == 0) {
+ owner_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID));
+ if (!owner_sid ||
+ !StringToSid(owner_sid, tok+6)) {
+ printf("Failed to parse owner sid\n");
+ return NULL;
+ }
+ continue;
+ }
+
+ if (strncmp(tok,"GROUP:", 6) == 0) {
+ grp_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID));
+ if (!grp_sid ||
+ !StringToSid(grp_sid, tok+6)) {
+ printf("Failed to parse group sid\n");
+ return NULL;
+ }
+ continue;
+ }
+
+ if (strncmp(tok,"ACL:", 4) == 0) {
+ SEC_ACE ace;
+ if (!parse_ace(&ace, tok+4)) {
+ printf("Failed to parse ACL %s\n", tok);
+ return NULL;
+ }
+ if(!add_ace(&dacl, &ace)) {
+ printf("Failed to add ACL %s\n", tok);
+ return NULL;
+ }
+ continue;
+ }
+
+ printf("Failed to parse security descriptor\n");
+ return NULL;
+ }
+
+ ret = make_sec_desc(ctx,revision, owner_sid, grp_sid,
+ NULL, dacl, &sd_size);
+
+ SAFE_FREE(grp_sid);
+ SAFE_FREE(owner_sid);
+
+ return ret;
+}
+
+
+/* print a ascii version of a security descriptor on a FILE handle */
+static void sec_desc_print(FILE *f, SEC_DESC *sd)
+{
+ fstring sidstr;
+ uint32 i;
+
+ printf("REVISION:%d\n", sd->revision);
+
+ /* Print owner and group sid */
+
+ if (sd->owner_sid) {
+ SidToString(sidstr, sd->owner_sid);
+ } else {
+ fstrcpy(sidstr, "");
+ }
+
+ printf("OWNER:%s\n", sidstr);
+
+ if (sd->grp_sid) {
+ SidToString(sidstr, sd->grp_sid);
+ } else {
+ fstrcpy(sidstr, "");
+ }
+
+ fprintf(f, "GROUP:%s\n", sidstr);
+
+ /* Print aces */
+ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+ SEC_ACE *ace = &sd->dacl->ace[i];
+ fprintf(f, "ACL:");
+ print_ace(f, ace);
+ fprintf(f, "\n");
+ }
+
+}
+
+/*****************************************************
+dump the acls for a file
+*******************************************************/
+static int cacl_dump(struct cli_state *cli, char *filename)
+{
+ int fnum;
+ SEC_DESC *sd;
+
+ if (test_args) return EXIT_OK;
+
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
+ if (fnum == -1) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ sd = cli_query_secdesc(cli, fnum, ctx);
+
+ if (!sd) {
+ printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ sec_desc_print(stdout, sd);
+
+ cli_close(cli, fnum);
+
+ return EXIT_OK;
+}
+
+/*****************************************************
+Change the ownership or group ownership of a file. Just
+because the NT docs say this can't be done :-). JRA.
+*******************************************************/
+
+static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
+ char *filename, char *new_username)
+{
+ int fnum;
+ DOM_SID sid;
+ SEC_DESC *sd, *old;
+ size_t sd_size;
+
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
+
+ if (fnum == -1) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ if (!StringToSid(&sid, new_username))
+ return EXIT_PARSE_ERROR;
+
+ old = cli_query_secdesc(cli, fnum, ctx);
+
+ cli_close(cli, fnum);
+
+ if (!old) {
+ printf("owner_set: Failed to query old descriptor\n");
+ return EXIT_FAILED;
+ }
+
+ sd = make_sec_desc(ctx,old->revision,
+ (change_mode == REQUEST_CHOWN) ? &sid : old->owner_sid,
+ (change_mode == REQUEST_CHGRP) ? &sid : old->grp_sid,
+ NULL, old->dacl, &sd_size);
+
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE);
+
+ if (fnum == -1) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ if (!cli_set_secdesc(cli, fnum, sd)) {
+ printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
+ }
+
+ cli_close(cli, fnum);
+
+ return EXIT_OK;
+}
+
+
+/* The MSDN is contradictory over the ordering of ACE entries in an ACL.
+ However NT4 gives a "The information may have been modified by a
+ computer running Windows NT 5.0" if denied ACEs do not appear before
+ allowed ACEs. */
+
+static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
+{
+ if (sec_ace_equal(ace1, ace2))
+ return 0;
+
+ if (ace1->type != ace2->type)
+ return ace2->type - ace1->type;
+
+ if (sid_compare(&ace1->trustee, &ace2->trustee))
+ return sid_compare(&ace1->trustee, &ace2->trustee);
+
+ if (ace1->flags != ace2->flags)
+ return ace1->flags - ace2->flags;
+
+ if (ace1->info.mask != ace2->info.mask)
+ return ace1->info.mask - ace2->info.mask;
+
+ if (ace1->size != ace2->size)
+ return ace1->size - ace2->size;
+
+ return memcmp(ace1, ace2, sizeof(SEC_ACE));
+}
+
+static void sort_acl(SEC_ACL *the_acl)
+{
+ uint32 i;
+ if (!the_acl) return;
+
+ qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), QSORT_CAST ace_compare);
+
+ for (i=1;i<the_acl->num_aces;) {
+ if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) {
+ int j;
+ for (j=i; j<the_acl->num_aces-1; j++) {
+ the_acl->ace[j] = the_acl->ace[j+1];
+ }
+ the_acl->num_aces--;
+ } else {
+ i++;
+ }
+ }
+}
+
+/*****************************************************
+set the ACLs on a file given an ascii description
+*******************************************************/
+static int cacl_set(struct cli_state *cli, char *filename,
+ char *the_acl, enum acl_mode mode)
+{
+ int fnum;
+ SEC_DESC *sd, *old;
+ uint32 i, j;
+ size_t sd_size;
+ int result = EXIT_OK;
+
+ sd = sec_desc_parse(the_acl);
+
+ if (!sd) return EXIT_PARSE_ERROR;
+ if (test_args) return EXIT_OK;
+
+ /* The desired access below is the only one I could find that works
+ with NT4, W2KP and Samba */
+
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
+
+ if (fnum == -1) {
+ printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ old = cli_query_secdesc(cli, fnum, ctx);
+
+ if (!old) {
+ printf("calc_set: Failed to query old descriptor\n");
+ return EXIT_FAILED;
+ }
+
+ cli_close(cli, fnum);
+
+ /* the logic here is rather more complex than I would like */
+ switch (mode) {
+ case SMB_ACL_DELETE:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ BOOL found = False;
+
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sec_ace_equal(&sd->dacl->ace[i],
+ &old->dacl->ace[j])) {
+ uint32 k;
+ for (k=j; k<old->dacl->num_aces-1;k++) {
+ old->dacl->ace[k] = old->dacl->ace[k+1];
+ }
+ old->dacl->num_aces--;
+ if (old->dacl->num_aces == 0) {
+ SAFE_FREE(old->dacl->ace);
+ SAFE_FREE(old->dacl);
+ old->off_dacl = 0;
+ }
+ found = True;
+ break;
+ }
+ }
+
+ if (!found) {
+ printf("ACL for ACE:");
+ print_ace(stdout, &sd->dacl->ace[i]);
+ printf(" not found\n");
+ }
+ }
+ break;
+
+ case SMB_ACL_MODIFY:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ BOOL found = False;
+
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sid_equal(&sd->dacl->ace[i].trustee,
+ &old->dacl->ace[j].trustee)) {
+ old->dacl->ace[j] = sd->dacl->ace[i];
+ found = True;
+ }
+ }
+
+ if (!found) {
+ fstring str;
+
+ SidToString(str, &sd->dacl->ace[i].trustee);
+ printf("ACL for SID %s not found\n", str);
+ }
+ }
+
+ break;
+
+ case SMB_ACL_ADD:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ add_ace(&old->dacl, &sd->dacl->ace[i]);
+ }
+ break;
+
+ case SMB_ACL_SET:
+ old = sd;
+ break;
+ }
+
+ /* Denied ACE entries must come before allowed ones */
+ sort_acl(old->dacl);
+
+ /* Create new security descriptor and set it */
+ sd = make_sec_desc(ctx,old->revision, old->owner_sid, old->grp_sid,
+ NULL, old->dacl, &sd_size);
+
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE);
+
+ if (fnum == -1) {
+ printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
+ return EXIT_FAILED;
+ }
+
+ if (!cli_set_secdesc(cli, fnum, sd)) {
+ printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
+ result = EXIT_FAILED;
+ }
+
+ /* Clean up */
+
+ cli_close(cli, fnum);
+
+ return result;
+}
+
+
+/*****************************************************
+return a connection to a server
+*******************************************************/
+struct cli_state *connect_one(char *share)
+{
+ struct cli_state *c;
+ struct nmb_name called, calling;
+ struct in_addr ip;
+ extern pstring global_myname;
+
+ fstrcpy(server,share+2);
+ share = strchr_m(server,'\\');
+ if (!share) return NULL;
+ *share = 0;
+ share++;
+
+ zero_ip(&ip);
+
+ make_nmb_name(&calling, global_myname, 0x0);
+ make_nmb_name(&called , server, 0x20);
+
+ again:
+ zero_ip(&ip);
+
+ /* have to open a new connection */
+ if (!(c=cli_initialise(NULL)) || !cli_connect(c, server, &ip)) {
+ DEBUG(0,("Connection to %s failed\n", server));
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ if (!cli_session_request(c, &calling, &called)) {
+ DEBUG(0,("session request to %s failed\n", called.name));
+ cli_shutdown(c);
+ if (strcmp(called.name, "*SMBSERVER")) {
+ make_nmb_name(&called , "*SMBSERVER", 0x20);
+ goto again;
+ }
+ return NULL;
+ }
+
+ DEBUG(4,(" session request ok\n"));
+
+ if (!cli_negprot(c)) {
+ DEBUG(0,("protocol negotiation failed\n"));
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ if (!got_pass) {
+ char *pass = getpass("Password: ");
+ if (pass) {
+ pstrcpy(password, pass);
+ }
+ }
+
+ if (!cli_session_setup(c, username,
+ password, strlen(password),
+ password, strlen(password),
+ lp_workgroup())) {
+ DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ DEBUG(4,(" session setup ok\n"));
+
+ if (!cli_send_tconX(c, share, "?????",
+ password, strlen(password)+1)) {
+ DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ DEBUG(4,(" tconx ok\n"));
+
+ return c;
+}
+
+
+static void usage(void)
+{
+ printf(
+"Usage: smbcacls //server1/share1 filename [options]\n\
+\n\
+\t-D <acls> delete an acl\n\
+\t-M <acls> modify an acl\n\
+\t-A <acls> add an acl\n\
+\t-S <acls> set acls\n\
+\t-C username change ownership of a file\n\
+\t-G username change group ownership of a file\n\
+\t-n don't resolve sids or masks to names\n\
+\t-h print help\n\
+\t-d debuglevel set debug output level\n\
+\t-U username user to autheticate as\n\
+\n\
+The username can be of the form username%%password or\n\
+workgroup\\username%%password.\n\n\
+An acl is of the form ACL:<SID>:type/flags/mask\n\
+You can string acls together with spaces, commas or newlines\n\
+");
+}
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc,char *argv[])
+{
+ char *share;
+ pstring filename;
+ extern char *optarg;
+ extern int optind;
+ int opt;
+ char *p;
+ struct cli_state *cli=NULL;
+ enum acl_mode mode = SMB_ACL_SET;
+ char *the_acl = NULL;
+ enum chown_mode change_mode = REQUEST_NONE;
+ int result;
+
+ ctx=talloc_init();
+
+ setlinebuf(stdout);
+
+ dbf = x_stderr;
+
+ if (argc < 3 || argv[1][0] == '-') {
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+ }
+
+ setup_logging(argv[0],True);
+
+ share = argv[1];
+ pstrcpy(filename, argv[2]);
+ all_string_sub(share,"/","\\",0);
+
+ argc -= 2;
+ argv += 2;
+
+ lp_load(dyn_CONFIGFILE,True,False,False);
+ load_interfaces();
+
+ if (getenv("USER")) {
+ pstrcpy(username,getenv("USER"));
+
+ if ((p=strchr_m(username,'%'))) {
+ *p = 0;
+ pstrcpy(password,p+1);
+ got_pass = True;
+ memset(strchr_m(getenv("USER"), '%') + 1, 'X',
+ strlen(password));
+ }
+ }
+
+ while ((opt = getopt(argc, argv, "U:nhS:D:A:M:C:G:td:")) != EOF) {
+ switch (opt) {
+ case 'U':
+ pstrcpy(username,optarg);
+ p = strchr_m(username,'%');
+ if (p) {
+ *p = 0;
+ pstrcpy(password, p+1);
+ got_pass = 1;
+ }
+ break;
+
+ case 'S':
+ the_acl = optarg;
+ mode = SMB_ACL_SET;
+ break;
+
+ case 'D':
+ the_acl = optarg;
+ mode = SMB_ACL_DELETE;
+ break;
+
+ case 'M':
+ the_acl = optarg;
+ mode = SMB_ACL_MODIFY;
+ break;
+
+ case 'A':
+ the_acl = optarg;
+ mode = SMB_ACL_ADD;
+ break;
+
+ case 'C':
+ pstrcpy(owner_username,optarg);
+ change_mode = REQUEST_CHOWN;
+ break;
+
+ case 'G':
+ pstrcpy(owner_username,optarg);
+ change_mode = REQUEST_CHGRP;
+ break;
+
+ case 'n':
+ numeric = 1;
+ break;
+
+ case 't':
+ test_args = 1;
+ break;
+
+ case 'h':
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+ }
+
+ /* Make connection to server */
+
+ if (!test_args) {
+ cli = connect_one(share);
+ if (!cli) {
+ talloc_destroy(ctx);
+ exit(EXIT_FAILED);
+ }
+ }
+
+ all_string_sub(filename, "/", "\\", 0);
+ if (filename[0] != '\\') {
+ pstring s;
+ s[0] = '\\';
+ safe_strcpy(&s[1], filename, sizeof(pstring)-1);
+ pstrcpy(filename, s);
+ }
+
+ /* Perform requested action */
+
+ if (change_mode != REQUEST_NONE) {
+ result = owner_set(cli, change_mode, filename, owner_username);
+ } else if (the_acl) {
+ result = cacl_set(cli, filename, the_acl, mode);
+ } else {
+ result = cacl_dump(cli, filename);
+ }
+
+ talloc_destroy(ctx);
+
+ return result;
+}
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
new file mode 100644
index 0000000000..d680fa4489
--- /dev/null
+++ b/source3/utils/smbcontrol.c
@@ -0,0 +1,509 @@
+/*
+ Unix SMB/CIFS implementation.
+ program to send control messages to Samba processes
+ Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) 2001, 2002 by Martin Pool
+
+ 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"
+
+extern BOOL AllowDebugChange;
+
+static struct {
+ char *name;
+ int value;
+} msg_types[] = {
+ {"debug", MSG_DEBUG},
+ {"force-election", MSG_FORCE_ELECTION},
+ {"ping", MSG_PING},
+ {"profile", MSG_PROFILE},
+ {"profilelevel", MSG_REQ_PROFILELEVEL},
+ {"debuglevel", MSG_REQ_DEBUGLEVEL},
+ {"printer-notify", MSG_PRINTER_NOTIFY},
+ {"close-share", MSG_SMB_FORCE_TDIS},
+ {"samsync", MSG_SMB_SAM_SYNC},
+ {"samrepl", MSG_SMB_SAM_REPL},
+ {"pool-usage", MSG_REQ_POOL_USAGE },
+ {"dmalloc-mark", MSG_REQ_DMALLOC_MARK },
+ {"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED },
+ {"shutdown", MSG_SHUTDOWN },
+ {NULL, -1}
+};
+
+time_t timeout_start;
+
+#define MAX_WAIT 10
+
+static void usage(BOOL doexit)
+{
+ int i;
+ if (doexit) {
+ printf("Usage: smbcontrol -i -s configfile\n");
+ printf(" smbcontrol <destination> <message-type> <parameters>\n\n");
+ } else {
+ printf("<destination> <message-type> <parameters>\n\n");
+ }
+ printf("\t<destination> is one of \"nmbd\", \"smbd\" or a process ID\n");
+ printf("\t<message-type> is one of: ");
+ for (i=0; msg_types[i].name; i++)
+ printf("%s%s", i?", ":"",msg_types[i].name);
+ printf("\n");
+ if (doexit) exit(1);
+}
+
+static int pong_count;
+static BOOL got_level;
+static BOOL pong_registered = False;
+static BOOL debuglevel_registered = False;
+static BOOL profilelevel_registered = False;
+
+
+/**
+ * Wait for replies for up to @p *max_secs seconds, or until @p
+ * max_replies are received. max_replies may be NULL in which case it
+ * is ignored.
+ *
+ * @note This is a pretty lame timeout; all it means is that after
+ * max_secs we won't look for any more messages.
+ **/
+static void wait_for_replies(int max_secs, int *max_replies)
+{
+ time_t timeout_end = time(NULL) + max_secs;
+
+ while ((!max_replies || (*max_replies)-- > 0)
+ && (time(NULL) < timeout_end)) {
+ message_dispatch();
+ }
+}
+
+
+/****************************************************************************
+a useful function for testing the message system
+****************************************************************************/
+void pong_function(int msg_type, pid_t src, void *buf, size_t len)
+{
+ pong_count++;
+ printf("PONG from PID %u\n",(unsigned int)src);
+}
+
+/****************************************************************************
+Prints out the current Debug level returned by MSG_DEBUGLEVEL
+****************************************************************************/
+void debuglevel_function(int msg_type, pid_t src, void *buf, size_t len)
+{
+ int i;
+ int debuglevel_class[DBGC_LAST];
+
+ memcpy(debuglevel_class, buf, len);
+
+ printf("Current debug level of PID %u is %d ",(unsigned int)src, debuglevel_class[0]);
+ for (i=1;i<DBGC_LAST;i++)
+ if (debuglevel_class[i])
+ printf("%s:%d ", debug_classname_from_index(i), debuglevel_class[i]);
+ printf("\n");
+
+ got_level = True;
+}
+
+/****************************************************************************
+Prints out the current Profile level returned by MSG_PROFILELEVEL
+****************************************************************************/
+void profilelevel_function(int msg_type, pid_t src, void *buf, size_t len)
+{
+ int level;
+ char *s=NULL;
+ memcpy(&level, buf, sizeof(int));
+
+ if (level) {
+ switch (level) {
+ case 1:
+ s = "off";
+ break;
+ case 3:
+ s = "count only";
+ break;
+ case 7:
+ s = "count and time";
+ break;
+ default:
+ s = "BOGUS";
+ break;
+ }
+ printf("Profiling %s on PID %u\n",s,(unsigned int)src);
+ } else {
+ printf("Profiling not available on PID %u\n",(unsigned int)src);
+ }
+ got_level = True;
+}
+
+/**
+ * Handle reply from POOL_USAGE.
+ **/
+static void pool_usage_cb(int msg_type, pid_t src_pid, void *buf, size_t len)
+{
+ printf("Got POOL_USAGE reply from pid%u:\n%.*s",
+ (unsigned int) src_pid, (int) len, (const char *) buf);
+}
+
+
+/**
+ * Send a message to a named destination
+ *
+ * @return False if an error occurred.
+ **/
+static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL duplicates)
+{
+ pid_t pid;
+ /* "smbd" is the only broadcast operation */
+ if (strequal(dest,"smbd")) {
+ TDB_CONTEXT *tdb;
+ BOOL ret;
+ int n_sent = 0;
+
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDWR, 0);
+ if (!tdb) {
+ fprintf(stderr,"Failed to open connections database in send_message.\n");
+ return False;
+ }
+
+ ret = message_send_all(tdb,msg_type, buf, len, duplicates,
+ &n_sent);
+ DEBUG(10,("smbcontrol/send_message: broadcast message to "
+ "%d processes\n", n_sent));
+ tdb_close(tdb);
+
+ return ret;
+ } else if (strequal(dest,"nmbd")) {
+ pid = pidfile_pid(dest);
+ if (pid == 0) {
+ fprintf(stderr,"Can't find pid for nmbd\n");
+ return False;
+ }
+ } else if (strequal(dest,"self")) {
+ pid = sys_getpid();
+ } else {
+ pid = atoi(dest);
+ if (pid == 0) {
+ fprintf(stderr,"Not a valid pid\n");
+ return False;
+ }
+ }
+
+ DEBUG(10,("smbcontrol/send_message: send message to pid%d\n", pid));
+ return message_send_pid(pid, msg_type, buf, len, duplicates);
+}
+
+/****************************************************************************
+evaluate a message type string
+****************************************************************************/
+static int parse_type(char *mtype)
+{
+ int i;
+ for (i=0;msg_types[i].name;i++) {
+ if (strequal(mtype, msg_types[i].name)) return msg_types[i].value;
+ }
+ return -1;
+}
+
+
+static void register_all(void)
+{
+ message_register(MSG_POOL_USAGE, pool_usage_cb);
+}
+
+
+/****************************************************************************
+do command
+****************************************************************************/
+static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
+{
+ int i, n, v;
+ int mtype;
+ BOOL retval=False;
+
+ mtype = parse_type(msg_name);
+ if (mtype == -1) {
+ fprintf(stderr,"Couldn't resolve message type: %s\n", msg_name);
+ return(False);
+ }
+
+ switch (mtype) {
+ case MSG_DEBUG: {
+ struct debuglevel_message dm;
+
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_DEBUG needs a parameter\n");
+ return(False);
+ }
+
+ ZERO_STRUCT(dm);
+ if (!debug_parse_params(params, dm.debuglevel_class, dm.debuglevel_class_isset)) {
+ fprintf(stderr, "MSG_DEBUG error. Expected <class name>:level\n");
+ return(False);
+ } else
+ send_message(dest, MSG_DEBUG, &dm, sizeof(dm), False);
+ break;
+ }
+
+ case MSG_PROFILE:
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_PROFILE needs a parameter\n");
+ return(False);
+ }
+ if (strequal(params[0], "off")) {
+ v = 0;
+ } else if (strequal(params[0], "count")) {
+ v = 1;
+ } else if (strequal(params[0], "on")) {
+ v = 2;
+ } else if (strequal(params[0], "flush")) {
+ v = 3;
+ } else {
+ fprintf(stderr,
+ "MSG_PROFILE parameter must be off, count, on, or flush\n");
+ return(False);
+ }
+ send_message(dest, MSG_PROFILE, &v, sizeof(int), False);
+ break;
+
+ case MSG_FORCE_ELECTION:
+ if (!strequal(dest, "nmbd")) {
+ fprintf(stderr,"force-election can only be sent to nmbd\n");
+ return(False);
+ }
+ send_message(dest, MSG_FORCE_ELECTION, NULL, 0, False);
+ break;
+
+ case MSG_REQ_PROFILELEVEL:
+ if (!profilelevel_registered) {
+ message_register(MSG_PROFILELEVEL, profilelevel_function);
+ profilelevel_registered = True;
+ }
+ got_level = False;
+ retval = send_message(dest, MSG_REQ_PROFILELEVEL, NULL, 0, True);
+ if (retval) {
+ timeout_start = time(NULL);
+ while (!got_level) {
+ message_dispatch();
+ if ((time(NULL) - timeout_start) > MAX_WAIT) {
+ fprintf(stderr,"profilelevel timeout\n");
+ break;
+ }
+ }
+ }
+ break;
+
+ case MSG_REQ_DEBUGLEVEL:
+ if (!debuglevel_registered) {
+ message_register(MSG_DEBUGLEVEL, debuglevel_function);
+ debuglevel_registered = True;
+ }
+ got_level = False;
+ retval = send_message(dest, MSG_REQ_DEBUGLEVEL, NULL, 0, True);
+ if (retval) {
+ timeout_start = time(NULL);
+ while (!got_level) {
+ message_dispatch();
+ if ((time(NULL) - timeout_start) > MAX_WAIT) {
+ fprintf(stderr,"debuglevel timeout\n");
+ break;
+ }
+ }
+ }
+ break;
+
+ case MSG_PRINTER_NOTIFY:
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr,"printer-notify can only be sent to smbd\n");
+ return(False);
+ }
+ if (!params || !params[0]) {
+ fprintf(stderr, "printer-notify needs a printer name\n");
+ return (False);
+ }
+ {
+ char msg[8 + sizeof(fstring)];
+ SIVAL(msg,0,PRINTER_CHANGE_ALL);
+ SIVAL(msg,4,0);
+ fstrcpy(&msg[8], params[0]);
+
+ retval = send_message(dest, MSG_PRINTER_NOTIFY, msg, 8 + strlen(params[0]) + 1, False);
+ }
+ break;
+
+ case MSG_SMB_FORCE_TDIS:
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr,"close-share can only be sent to smbd\n");
+ return(False);
+ }
+ if (!params || !params[0]) {
+ fprintf(stderr, "close-share needs a share name or '*'\n");
+ return (False);
+ }
+ retval = send_message(dest, MSG_SMB_FORCE_TDIS, params[0],
+ strlen(params[0]) + 1, False);
+ break;
+
+ case MSG_SMB_SAM_SYNC:
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr, "samsync can only be sent to smbd\n");
+ return False;
+ }
+
+ if (params) {
+ fprintf(stderr, "samsync does not take any parameters\n");
+ return False;
+ }
+
+ retval = send_message(dest, MSG_SMB_SAM_SYNC, NULL, 0, False);
+
+ break;
+
+ case MSG_SMB_SAM_REPL: {
+ uint32 seqnum;
+
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr, "sam repl can only be sent to smbd\n");
+ return False;
+ }
+
+ if (!params || !params[0]) {
+ fprintf(stderr, "SAM_REPL needs a parameter\n");
+ return False;
+ }
+
+ seqnum = atoi(params[0]);
+
+ retval = send_message(dest, MSG_SMB_SAM_SYNC,
+ (char *)&seqnum, sizeof(uint32), False);
+
+ break;
+ }
+
+ case MSG_PING:
+ if (!pong_registered) {
+ message_register(MSG_PONG, pong_function);
+ pong_registered = True;
+ }
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_PING needs a parameter\n");
+ return(False);
+ }
+ n = atoi(params[0]);
+ pong_count = 0;
+ for (i=0;i<n;i++) {
+ if (iparams > 1)
+ retval = send_message(dest, MSG_PING, params[1], strlen(params[1]) + 1, True);
+ else
+ retval = send_message(dest, MSG_PING, NULL, 0, True);
+ if (retval == False)
+ return False;
+ }
+ wait_for_replies(MAX_WAIT, &n);
+ if (n > 0) {
+ fprintf(stderr,"PING timeout\n");
+ }
+ break;
+
+ case MSG_REQ_POOL_USAGE:
+ if (!send_message(dest, MSG_REQ_POOL_USAGE, NULL, 0, True))
+ return False;
+ wait_for_replies(MAX_WAIT, NULL);
+
+ break;
+
+ case MSG_REQ_DMALLOC_LOG_CHANGED:
+ case MSG_REQ_DMALLOC_MARK:
+ if (!send_message(dest, mtype, NULL, 0, False))
+ return False;
+ break;
+
+ case MSG_SHUTDOWN:
+ if (!send_message(dest, MSG_SHUTDOWN, NULL, 0, False))
+ return False;
+ break;
+ }
+
+ return (True);
+}
+
+ int main(int argc, char *argv[])
+{
+ int opt;
+ char temp[255];
+ extern int optind;
+ BOOL interactive = False;
+
+ AllowDebugChange = False;
+ DEBUGLEVEL = 0;
+
+ setup_logging(argv[0],True);
+
+ if (argc < 2) usage(True);
+
+ while ((opt = getopt(argc, argv,"is:")) != EOF) {
+ switch (opt) {
+ case 'i':
+ interactive = True;
+ break;
+ case 's':
+ pstrcpy(dyn_CONFIGFILE, optarg);
+ break;
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ usage(True);
+ }
+ }
+
+ lp_load(dyn_CONFIGFILE,False,False,False);
+
+ if (!message_init()) exit(1);
+
+ argc -= optind;
+ argv = &argv[optind];
+
+ register_all();
+
+ if (!interactive) {
+ if (argc < 2) usage(True);
+ /* Need to invert sense of return code -- samba
+ * routines mostly return True==1 for success, but
+ * shell needs 0. */
+ return ! do_command(argv[0],argv[1], argc-2, argc > 2 ? &argv[2] : 0);
+ }
+
+ while (True) {
+ char *myargv[4];
+ int myargc;
+
+ printf("smbcontrol> ");
+ if (!fgets(temp, sizeof(temp)-1, stdin)) break;
+ myargc = 0;
+ while ((myargc < 4) &&
+ (myargv[myargc] = strtok(myargc?NULL:temp," \t\n"))) {
+ myargc++;
+ }
+ if (!myargc) break;
+ if (strequal(myargv[0],"q")) break;
+ if (myargc < 2)
+ usage(False);
+ else if (!do_command(myargv[0],myargv[1],myargc-2,myargc > 2 ? &myargv[2] : 0))
+ usage(False);
+ }
+ return(0);
+}
+
diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c
new file mode 100644
index 0000000000..5a2d394706
--- /dev/null
+++ b/source3/utils/smbfilter.c
@@ -0,0 +1,246 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB filter/socket plugin
+ Copyright (C) Andrew Tridgell 1999
+
+ 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 "smb.h"
+
+#define SECURITY_MASK 0
+#define SECURITY_SET 0
+
+/* this forces non-unicode */
+#define CAPABILITY_MASK 0
+#define CAPABILITY_SET 0
+
+/* and non-unicode for the client too */
+#define CLI_CAPABILITY_MASK 0
+#define CLI_CAPABILITY_SET 0
+
+static char *netbiosname;
+static char packet[BUFFER_SIZE];
+
+static void save_file(const char *fname, void *packet, size_t length)
+{
+ int fd;
+ fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd == -1) {
+ perror(fname);
+ return;
+ }
+ if (write(fd, packet, length) != length) {
+ fprintf(stderr,"Failed to write %s\n", fname);
+ return;
+ }
+ close(fd);
+ printf("Wrote %d bytes to %s\n", length, fname);
+}
+
+static void filter_reply(char *buf)
+{
+ int msg_type = CVAL(buf,0);
+ int type = CVAL(buf,smb_com);
+ unsigned x;
+
+ if (msg_type) return;
+
+ switch (type) {
+
+ case SMBnegprot:
+ /* force the security bits */
+ x = CVAL(buf, smb_vwv1);
+ x = (x | SECURITY_SET) & ~SECURITY_MASK;
+ SCVAL(buf, smb_vwv1, x);
+
+ /* force the capabilities */
+ x = IVAL(buf,smb_vwv9+1);
+ x = (x | CAPABILITY_SET) & ~CAPABILITY_MASK;
+ SIVAL(buf, smb_vwv9+1, x);
+ break;
+
+ }
+}
+
+static void filter_request(char *buf)
+{
+ int msg_type = CVAL(buf,0);
+ int type = CVAL(buf,smb_com);
+ pstring name1,name2;
+ unsigned x;
+
+ if (msg_type) {
+ /* it's a netbios special */
+ switch (msg_type) {
+ case 0x81:
+ /* session request */
+ name_extract(buf,4,name1);
+ name_extract(buf,4 + name_len(buf + 4),name2);
+ d_printf("sesion_request: %s -> %s\n",
+ name1, name2);
+ if (netbiosname) {
+ /* replace the destination netbios name */
+ name_mangle(netbiosname, buf+4, 0x20);
+ }
+ }
+ return;
+ }
+
+ /* it's an ordinary SMB request */
+ switch (type) {
+ case SMBsesssetupX:
+ /* force the client capabilities */
+ x = IVAL(buf,smb_vwv11);
+ d_printf("SMBsesssetupX cap=0x%08x\n", x);
+ d_printf("pwlen=%d/%d\n", SVAL(buf, smb_vwv7), SVAL(buf, smb_vwv8));
+ system("mv sessionsetup.dat sessionsetup1.dat");
+ save_file("sessionsetup.dat", smb_buf(buf), SVAL(buf, smb_vwv7));
+ x = (x | CLI_CAPABILITY_SET) & ~CLI_CAPABILITY_MASK;
+ SIVAL(buf, smb_vwv11, x);
+ break;
+ }
+
+}
+
+
+static void filter_child(int c, struct in_addr dest_ip)
+{
+ int s;
+
+ /* we have a connection from a new client, now connect to the server */
+ s = open_socket_out(SOCK_STREAM, &dest_ip, 445, LONG_CONNECT_TIMEOUT);
+
+ if (s == -1) {
+ d_printf("Unable to connect to %s\n", inet_ntoa(dest_ip));
+ exit(1);
+ }
+
+ while (c != -1 || s != -1) {
+ fd_set fds;
+ int num;
+
+ FD_ZERO(&fds);
+ if (s != -1) FD_SET(s, &fds);
+ if (c != -1) FD_SET(c, &fds);
+
+ num = sys_select_intr(MAX(s+1, c+1),&fds,NULL,NULL,NULL);
+ if (num <= 0) continue;
+
+ if (c != -1 && FD_ISSET(c, &fds)) {
+ if (!receive_smb(c, packet, 0)) {
+ d_printf("client closed connection\n");
+ exit(0);
+ }
+ filter_request(packet);
+ if (!send_smb(s, packet)) {
+ d_printf("server is dead\n");
+ exit(1);
+ }
+ }
+ if (s != -1 && FD_ISSET(s, &fds)) {
+ if (!receive_smb(s, packet, 0)) {
+ d_printf("server closed connection\n");
+ exit(0);
+ }
+ filter_reply(packet);
+ if (!send_smb(c, packet)) {
+ d_printf("client is dead\n");
+ exit(1);
+ }
+ }
+ }
+ d_printf("Connection closed\n");
+ exit(0);
+}
+
+
+static void start_filter(char *desthost)
+{
+ int s, c;
+ struct in_addr dest_ip;
+
+ CatchChild();
+
+ /* start listening on port 445 locally */
+ s = open_socket_in(SOCK_STREAM, 445, 0, 0, True);
+
+ if (s == -1) {
+ d_printf("bind failed\n");
+ exit(1);
+ }
+
+ if (listen(s, 5) == -1) {
+ d_printf("listen failed\n");
+ }
+
+ if (!resolve_name(desthost, &dest_ip, 0x20)) {
+ d_printf("Unable to resolve host %s\n", desthost);
+ exit(1);
+ }
+
+ while (1) {
+ fd_set fds;
+ int num;
+ struct sockaddr addr;
+ socklen_t in_addrlen = sizeof(addr);
+
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+
+ num = sys_select_intr(s+1,&fds,NULL,NULL,NULL);
+ if (num > 0) {
+ c = accept(s, &addr, &in_addrlen);
+ if (c != -1) {
+ if (fork() == 0) {
+ close(s);
+ filter_child(c, dest_ip);
+ exit(0);
+ } else {
+ close(c);
+ }
+ }
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *desthost;
+ pstring configfile;
+
+ setup_logging(argv[0],True);
+
+ pstrcpy(configfile,dyn_CONFIGFILE);
+
+ if (argc < 2) {
+ fprintf(stderr,"smbfilter <desthost> <netbiosname>\n");
+ exit(1);
+ }
+
+ desthost = argv[1];
+ if (argc > 2) {
+ netbiosname = argv[2];
+ }
+
+ if (!lp_load(configfile,True,False,False)) {
+ d_printf("Unable to load config file\n");
+ }
+
+ start_filter(desthost);
+ return 0;
+}
diff --git a/source3/utils/smbgroupedit.c b/source3/utils/smbgroupedit.c
new file mode 100644
index 0000000000..cfa0dd8af9
--- /dev/null
+++ b/source3/utils/smbgroupedit.c
@@ -0,0 +1,397 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-2000,
+ * Copyright (C) Jean François Micouleau 1998-2001.
+ *
+ * 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"
+
+extern pstring global_myname;
+extern DOM_SID global_sam_sid;
+
+/*
+ * Next two lines needed for SunOS and don't
+ * hurt anything else...
+ */
+extern char *optarg;
+extern int optind;
+
+/*********************************************************
+ Print command usage on stderr and die.
+**********************************************************/
+static void usage(void)
+{
+ if (getuid() == 0) {
+ printf("smbgroupedit options\n");
+ } else {
+ printf("You need to be root to use this tool!\n");
+ }
+ printf("options:\n");
+ printf(" -a group create new group\n");
+ printf(" -n group NT group name\n");
+ printf(" -p privilege only local\n");
+ printf(" -v list groups\n");
+ printf(" -l long list (include details)\n");
+ printf(" -s short list (default)\n");
+ printf(" -c SID change group\n");
+ printf(" -u unix group\n");
+ printf(" -x group delete this group\n");
+ printf("\n");
+ printf(" -t[b|d|l] type: builtin, domain, local \n");
+ exit(1);
+}
+
+/*********************************************************
+ Figure out if the input was an NT group or a SID string.
+ Return the SID.
+**********************************************************/
+static BOOL get_sid_from_input(DOM_SID *sid, char *input)
+{
+ GROUP_MAP map;
+
+ if (StrnCaseCmp( input, "S-", 2)) {
+ /* Perhaps its the NT group name? */
+ if (!get_group_map_from_ntname(input, &map, MAPPING_WITHOUT_PRIV)) {
+ printf("NT Group %s doesn't exist in mapping DB\n", input);
+ return False;
+ } else {
+ *sid = map.sid;
+ }
+ } else {
+ if (!string_to_sid(sid, input)) {
+ printf("converting sid %s from a string failed!\n", input);
+ return False;
+ }
+ }
+ return True;
+}
+
+/*********************************************************
+ add a group.
+**********************************************************/
+static int addgroup(char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege)
+{
+ PRIVILEGE_SET se_priv;
+ gid_t gid;
+ DOM_SID sid;
+ fstring string_sid;
+ fstring name, comment;
+
+ gid=nametogid(group);
+ if (gid==-1) {
+ printf("unix group %s doesn't exist!\n", group);
+ return -1;
+ }
+
+ local_gid_to_sid(&sid, gid);
+
+ sid_to_string(string_sid, &sid);
+
+ if (ntgroup==NULL)
+ fstrcpy(name, group);
+ else
+ fstrcpy(name, ntgroup);
+
+ if (ntcomment==NULL)
+ fstrcpy(comment, "Local Unix group");
+ else
+ fstrcpy(comment, ntcomment);
+
+ init_privilege(&se_priv);
+ if (privilege!=NULL)
+ convert_priv_from_text(&se_priv, privilege);
+
+ if(!add_initial_entry(gid, string_sid, sid_type, name, comment, se_priv, PR_ACCESS_FROM_NETWORK)) {
+ printf("adding entry for group %s failed!\n", group);
+ free_privilege(&se_priv);
+ return -1;
+ }
+
+ free_privilege(&se_priv);
+ return 0;
+}
+
+/*********************************************************
+ Change a group.
+**********************************************************/
+static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege)
+{
+ DOM_SID sid;
+ GROUP_MAP map;
+ gid_t gid;
+
+ if (!get_sid_from_input(&sid, sid_string)) {
+ return -1;
+ }
+
+ /* Get the current mapping from the database */
+ if(!get_group_map_from_sid(sid, &map, MAPPING_WITH_PRIV)) {
+ printf("This SID does not exist in the database\n");
+ return -1;
+ }
+
+ /* If a new Unix group is specified, check and change */
+ if (group!=NULL) {
+ gid=nametogid(group);
+ if (gid==-1) {
+ printf("The UNIX group does not exist\n");
+ return -1;
+ } else
+ map.gid=gid;
+ }
+
+ /*
+ * Allow changing of group type only between domain and local
+ * We disallow changing Builtin groups !!! (SID problem)
+ */
+ if (sid_type==SID_NAME_ALIAS
+ || sid_type==SID_NAME_DOM_GRP
+ || sid_type==SID_NAME_UNKNOWN) {
+ if (map.sid_name_use==SID_NAME_ALIAS
+ || map.sid_name_use==SID_NAME_DOM_GRP
+ || map.sid_name_use==SID_NAME_UNKNOWN) {
+ map.sid_name_use=sid_type;
+ } else {
+ printf("cannot change group type to builtin\n");
+ };
+ } else {
+ printf("cannot change group type from builtin\n");
+ }
+
+ if (ntgroup!=NULL)
+ fstrcpy(map.nt_name, ntgroup);
+
+ /* Change comment if new one */
+ if (groupdesc!=NULL)
+ fstrcpy(map.comment, groupdesc);
+
+ /* Change the privilege if new one */
+ if (privilege!=NULL)
+ convert_priv_from_text(&map.priv_set, privilege);
+
+ if (!add_mapping_entry(&map, TDB_REPLACE)) {
+ printf("Count not update group database\n");
+ free_privilege(&map.priv_set);
+ return -1;
+ }
+
+ free_privilege(&map.priv_set);
+ return 0;
+}
+
+/*********************************************************
+ Delete the group.
+**********************************************************/
+static int deletegroup(char *group)
+{
+ DOM_SID sid;
+
+ if (!get_sid_from_input(&sid, group)) {
+ return -1;
+ }
+
+ if(!group_map_remove(sid)) {
+ printf("removing group %s from the mapping db failed!\n", group);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*********************************************************
+ List the groups.
+**********************************************************/
+static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list)
+{
+ int entries,i;
+ GROUP_MAP *map=NULL;
+ fstring string_sid;
+ fstring group_type;
+ fstring priv_text;
+
+ if (!long_list)
+ printf("NT group (SID) -> Unix group\n");
+
+ if (!enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV))
+ return -1;
+
+ for (i=0; i<entries; i++) {
+ decode_sid_name_use(group_type, (map[i]).sid_name_use);
+ sid_to_string(string_sid, &map[i].sid);
+ convert_priv_to_text(&(map[i].priv_set), priv_text);
+ free_privilege(&(map[i].priv_set));
+
+ if (!long_list)
+ printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid));
+ else {
+ printf("%s\n", map[i].nt_name);
+ printf("\tSID : %s\n", string_sid);
+ printf("\tUnix group: %s\n", gidtoname(map[i].gid));
+ printf("\tGroup type: %s\n", group_type);
+ printf("\tComment : %s\n", map[i].comment);
+ printf("\tPrivilege : %s\n\n", priv_text);
+ }
+ }
+
+ return 0;
+}
+
+/*********************************************************
+ Start here.
+**********************************************************/
+int main (int argc, char **argv)
+{
+ int ch;
+ BOOL add_group = False;
+ BOOL view_group = False;
+ BOOL change_group = False;
+ BOOL delete_group = False;
+ BOOL nt_group = False;
+ BOOL priv = False;
+ BOOL group_type = False;
+ BOOL long_list = False;
+
+ char *group = NULL;
+ char *sid = NULL;
+ char *ntgroup = NULL;
+ char *privilege = NULL;
+ char *groupt = NULL;
+ char *group_desc = NULL;
+
+ enum SID_NAME_USE sid_type;
+
+ setup_logging("groupedit", True);
+
+ if (argc < 2) {
+ usage();
+ return 0;
+ }
+
+ if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n",
+ dyn_CONFIGFILE);
+ exit(1);
+ }
+
+ if(!initialize_password_db(True)) {
+ fprintf(stderr, "Can't setup password database vectors.\n");
+ exit(1);
+ }
+
+ if(pdb_generate_sam_sid()==False) {
+ printf("Can not read machine SID\n");
+ return 0;
+ }
+
+ while ((ch = getopt(argc, argv, "a:c:d:ln:p:st:u:vx:")) != EOF) {
+ switch(ch) {
+ case 'a':
+ add_group = True;
+ group=optarg;
+ break;
+ case 'c':
+ change_group = True;
+ sid=optarg;
+ break;
+ case 'd':
+ group_desc=optarg;
+ break;
+ case 'l':
+ long_list = True;
+ break;
+ case 'n':
+ nt_group = True;
+ ntgroup=optarg;
+ break;
+ case 'p':
+ priv = True;
+ privilege=optarg;
+ break;
+ case 's':
+ long_list = False;
+ break;
+ case 't':
+ group_type = True;
+ groupt=optarg;
+ break;
+ case 'u':
+ group=optarg;
+ break;
+ case 'v':
+ view_group = True;
+ break;
+ case 'x':
+ delete_group = True;
+ group=optarg;
+ break;
+ /*default:
+ usage();*/
+ }
+ }
+
+
+ if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) {
+ fprintf (stderr, "Incompatible options on command line!\n");
+ usage();
+ exit(1);
+ }
+
+ /* no option on command line -> list groups */
+ if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0)
+ view_group = True;
+
+
+ if (group_type==False)
+ sid_type=SID_NAME_UNKNOWN;
+ else {
+ switch (groupt[0]) {
+ case 'l':
+ case 'L':
+ sid_type=SID_NAME_ALIAS;
+ break;
+ case 'd':
+ case 'D':
+ sid_type=SID_NAME_DOM_GRP;
+ break;
+ case 'b':
+ case 'B':
+ sid_type=SID_NAME_WKN_GRP;
+ break;
+ default:
+ sid_type=SID_NAME_UNKNOWN;
+ break;
+ }
+ }
+
+ if (add_group)
+ return addgroup(group, sid_type, ntgroup, group_desc, privilege);
+
+ if (view_group)
+ return listgroup(sid_type, long_list);
+
+ if (delete_group)
+ return deletegroup(group);
+
+ if (change_group) {
+ return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege);
+ }
+
+ usage();
+
+ return 0;
+}
diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
index 167eb2ed5f..a96fad0cdb 100644
--- a/source3/utils/smbpasswd.c
+++ b/source3/utils/smbpasswd.c
@@ -1,13 +1,12 @@
-#ifdef SMB_PASSWD
-
/*
- * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright
- * (C) Jeremy Allison 1995.
+ * Unix SMB/CIFS implementation.
+ * Copyright (C) Jeremy Allison 1995-1998
+ * Copyright (C) Tim Potter 2001
*
- * 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 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
@@ -16,441 +15,603 @@
*
* 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.
- */
+ * Mass Ave, Cambridge, MA 02139, USA. */
#include "includes.h"
-#include "des.h"
-/* Static buffers we will return. */
-static struct smb_passwd pw_buf;
-static pstring user_name;
-static unsigned char smbpwd[16];
-static unsigned char smbntpwd[16];
+extern pstring global_myname;
+extern BOOL AllowDebugChange;
+
+/*
+ * Next two lines needed for SunOS and don't
+ * hurt anything else...
+ */
+extern char *optarg;
+extern int optind;
+
+/* forced running in root-mode */
+static BOOL local_mode;
+static BOOL got_pass = False, got_username = False;
+static int local_flags = 0;
+static BOOL stdin_passwd_get = False;
+static fstring user_name, user_password;
+static char *new_domain = NULL;
+static char *new_passwd = NULL;
+static char *old_passwd = NULL;
+static char *remote_machine = NULL;
+static pstring configfile;
+
+#ifdef WITH_LDAP_SAM
+static fstring ldap_secret;
+#endif
+
+/*********************************************************
+ Print command usage on stderr and die.
+**********************************************************/
+static void usage(void)
+{
+ printf("When run by root:\n");
+ printf(" smbpasswd [options] [username] [password]\n");
+ printf("otherwise:\n");
+ printf(" smbpasswd [options] [password]\n\n");
+
+ printf("options:\n");
+ printf(" -L local mode (must be first option)\n");
+ printf(" -h print this usage message\n");
+ printf(" -s use stdin for password prompt\n");
+ printf(" -c smb.conf file Use the given path to the smb.conf file\n");
+ printf(" -D LEVEL debug level\n");
+ printf(" -r MACHINE remote machine\n");
+ printf(" -U USER remote username\n");
+
+ printf("extra options when run by root or in local mode:\n");
+ printf(" -a add user\n");
+ printf(" -d disable user\n");
+ printf(" -e enable user\n");
+ printf(" -i interdomain trust account\n");
+ printf(" -m machine trust account\n");
+ printf(" -n set no password\n");
+#ifdef WITH_LDAP_SAM
+ printf(" -w ldap admin password\n");
+#endif
+ printf(" -x delete user\n");
+ printf(" -R ORDER name resolve order\n");
+
+ exit(1);
+}
+
+static void set_line_buffering(FILE *f)
+{
+ setvbuf(f, NULL, _IOLBF, 0);
+}
-static int gethexpwd(char *p, char *pwd)
+/*******************************************************************
+ Process command line options
+ ******************************************************************/
+static void process_options(int argc, char **argv, BOOL amroot)
{
- int i;
- unsigned char lonybble, hinybble;
- char *hexchars = "0123456789ABCDEF";
- char *p1, *p2;
- for (i = 0; i < 32; i += 2) {
- hinybble = toupper(p[i]);
- lonybble = toupper(p[i + 1]);
-
- p1 = strchr(hexchars, hinybble);
- p2 = strchr(hexchars, lonybble);
- if (!p1 || !p2)
- return (False);
-
- hinybble = PTR_DIFF(p1, hexchars);
- lonybble = PTR_DIFF(p2, hexchars);
-
- pwd[i / 2] = (hinybble << 4) | lonybble;
+ int ch;
+
+ if (amroot)
+ local_flags = LOCAL_SET_PASSWORD;
+
+ ZERO_STRUCT(user_name);
+ ZERO_STRUCT(user_password);
+
+ user_name[0] = '\0';
+
+ while ((ch = getopt(argc, argv, "c:axdehmnj:r:sw:R:D:U:L")) != EOF) {
+ switch(ch) {
+ case 'L':
+ local_mode = amroot = True;
+ local_flags = LOCAL_SET_PASSWORD;
+ break;
+ case 'c':
+ pstrcpy(configfile,optarg);
+ break;
+ case 'a':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_ADD_USER;
+ break;
+ case 'x':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_DELETE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'd':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_DISABLE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'e':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_ENABLE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'm':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_TRUST_ACCOUNT;
+ break;
+ case 'i':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_INTERDOM_ACCOUNT;
+ break;
+ case 'j':
+ if (!amroot) goto bad_args;
+ d_printf("See 'net rpc join' for this functionality\n");
+ exit(1);
+ break;
+ case 'n':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_SET_NO_PASSWORD;
+ new_passwd = smb_xstrdup("NO PASSWORD");
+ break;
+ case 'r':
+ remote_machine = optarg;
+ break;
+ case 's':
+ set_line_buffering(stdin);
+ set_line_buffering(stdout);
+ set_line_buffering(stderr);
+ stdin_passwd_get = True;
+ break;
+ case 'w':
+ if (!amroot) goto bad_args;
+#ifdef WITH_LDAP_SAM
+ local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
+ fstrcpy(ldap_secret, optarg);
+ break;
+#else
+ printf("-w not available unless configured --with-ldap\n");
+ goto bad_args;
+#endif
+ case 'R':
+ if (!amroot) goto bad_args;
+ lp_set_name_resolve_order(optarg);
+ break;
+ case 'D':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+ case 'U': {
+ char *lp;
+
+ got_username = True;
+ fstrcpy(user_name, optarg);
+
+ if ((lp = strchr(user_name, '%'))) {
+ *lp = 0;
+ fstrcpy(user_password, lp + 1);
+ got_pass = True;
+ memset(strchr_m(optarg, '%') + 1, 'X',
+ strlen(user_password));
+ }
+
+ break;
+ }
+ case 'h':
+ default:
+bad_args:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ switch(argc) {
+ case 0:
+ if (!got_username)
+ fstrcpy(user_name, "");
+ break;
+ case 1:
+ if (!amroot) {
+ new_passwd = argv[0];
+ break;
+ }
+ if (got_username)
+ usage();
+ fstrcpy(user_name, argv[0]);
+ break;
+ case 2:
+ if (!amroot || got_username || got_pass)
+ usage();
+ fstrcpy(user_name, argv[0]);
+ new_passwd = smb_xstrdup(argv[1]);
+ break;
+ default:
+ usage();
}
- return (True);
+
}
-struct smb_passwd *
-_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd,
- BOOL *got_valid_nt_entry, long *pwd_seekpos)
+/*************************************************************
+ Utility function to prompt for passwords from stdin. Each
+ password entered must end with a newline.
+*************************************************************/
+static char *stdin_new_passwd(void)
{
- char linebuf[256];
- unsigned char c;
- unsigned char *p;
- long uidval;
- long linebuf_len;
+ static fstring new_passwd;
+ size_t len;
+
+ ZERO_ARRAY(new_passwd);
/*
- * Scan the file, a line at a time and check if the name matches.
+ * if no error is reported from fgets() and string at least contains
+ * the newline that ends the password, then replace the newline with
+ * a null terminator.
*/
- while (!feof(fp)) {
- linebuf[0] = '\0';
- *pwd_seekpos = ftell(fp);
+ if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) {
+ if ((len = strlen(new_passwd)) > 0) {
+ if(new_passwd[len-1] == '\n')
+ new_passwd[len - 1] = 0;
+ }
+ }
+ return(new_passwd);
+}
- fgets(linebuf, 256, fp);
- if (ferror(fp))
- return NULL;
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n')
- break;
- }
- } else
- linebuf[linebuf_len - 1] = '\0';
+/*************************************************************
+ Utility function to get passwords via tty or stdin
+ Used if the '-s' option is set to silently get passwords
+ to enable scripting.
+*************************************************************/
+static char *get_pass( char *prompt, BOOL stdin_get)
+{
+ char *p;
+ if (stdin_get) {
+ p = stdin_new_passwd();
+ } else {
+ p = getpass(prompt);
+ }
+ return smb_xstrdup(p);
+}
- if ((linebuf[0] == 0) && feof(fp))
- break;
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
- *
- * if Windows NT compatible passwords are also present.
- */
+/*************************************************************
+ Utility function to prompt for new password.
+*************************************************************/
+static char *prompt_for_new_password(BOOL stdin_get)
+{
+ char *p;
+ fstring new_passwd;
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- continue;
- p = (unsigned char *) strchr(linebuf, ':');
- if (p == NULL)
- continue;
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (!strequal(user_name, name))
- continue;
+ ZERO_ARRAY(new_passwd);
+
+ p = get_pass("New SMB password:", stdin_get);
+
+ fstrcpy(new_passwd, p);
+ SAFE_FREE(p);
+
+ p = get_pass("Retype new SMB password:", stdin_get);
+
+ if (strcmp(p, new_passwd)) {
+ fprintf(stderr, "Mismatch - password unchanged.\n");
+ ZERO_ARRAY(new_passwd);
+ SAFE_FREE(p);
+ return NULL;
+ }
+
+ return p;
+}
+
+
+/*************************************************************
+ Change a password either locally or remotely.
+*************************************************************/
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
- if (!isdigit(*p))
- return (False);
+static BOOL password_change(const char *remote_machine, char *user_name,
+ char *old_passwd, char *new_passwd, int local_flags)
+{
+ BOOL ret;
+ pstring err_str;
+ pstring msg_str;
- uidval = atoi((char *) p);
- while (*p && isdigit(*p))
- p++;
+ if (remote_machine != NULL) {
+ if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
+ LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
+ /* these things can't be done remotely yet */
+ return False;
+ }
+ ret = remote_password_change(remote_machine, user_name,
+ old_passwd, new_passwd, err_str, sizeof(err_str));
+ if(*err_str)
+ fprintf(stderr, err_str);
+ return ret;
+ }
+
+ ret = local_password_change(user_name, local_flags, new_passwd,
+ err_str, sizeof(err_str), msg_str, sizeof(msg_str));
- if (*p != ':')
- return (False);
+ if(*msg_str)
+ printf(msg_str);
+ if(*err_str)
+ fprintf(stderr, err_str);
+
+ return ret;
+}
+
+#ifdef WITH_LDAP_SAM
+/*******************************************************************
+ Store the LDAP admin password in secrets.tdb
+ ******************************************************************/
+static BOOL store_ldap_admin_pw (char* pw)
+{
+ if (!pw)
+ return False;
+
+ if (!secrets_init())
+ return False;
+
+ return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw);
+}
+#endif
+
+
+/*************************************************************
+ Handle password changing for root.
+*************************************************************/
+
+static int process_root(void)
+{
+ struct passwd *pwd;
+ int result = 0;
+
+#ifdef WITH_LDAP_SAM
+ if (local_flags & LOCAL_SET_LDAP_ADMIN_PW)
+ {
+ printf("Setting stored password for \"%s\" in secrets.tdb\n",
+ lp_ldap_admin_dn());
+ if (!store_ldap_admin_pw(ldap_secret))
+ DEBUG(0,("ERROR: Failed to store the ldap admin password!\n"));
+ goto done;
+ }
+#endif
+
+ /*
+ * Ensure both add/delete user are not set
+ * Ensure add/delete user and either remote machine or join domain are
+ * not both set.
+ */
+ if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) ||
+ ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) &&
+ (remote_machine != NULL))) {
+ usage();
+ }
+
+ /* Only load interfaces if we are doing network operations. */
+
+ if (remote_machine) {
+ load_interfaces();
+ }
+
+ if (!user_name[0] && (pwd = sys_getpwuid(geteuid()))) {
+ fstrcpy(user_name, pwd->pw_name);
+ }
+
+ if (!user_name[0]) {
+ fprintf(stderr,"You must specify a username\n");
+ exit(1);
+ }
+
+ if (local_flags & LOCAL_TRUST_ACCOUNT) {
+ /* add the $ automatically */
+ static fstring buf;
/*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
+ * Remove any trailing '$' before we
+ * generate the initial machine password.
*/
- p++;
- *pwd_seekpos += PTR_DIFF(p, linebuf); /* Save exact position
- * of passwd in file -
- * this is used by
- * smbpasswd.c */
- if (*p == '*' || *p == 'X') {
- /* Password deliberately invalid - end here. */
- *valid_old_pwd = False;
- *got_valid_nt_entry = False;
- pw_buf.smb_nt_passwd = NULL; /* No NT password (yet)*/
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- /* NT Entry was valid - even if 'X' or '*', can be overwritten */
- *got_valid_nt_entry = True;
- if (*p != '*' && *p != 'X') {
- if(gethexpwd(p,smbntpwd))
- pw_buf.smb_nt_passwd = smbntpwd;
- }
- }
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- pw_buf.smb_passwd = NULL; /* No password */
- return (&pw_buf);
+
+ if (user_name[strlen(user_name)-1] == '$') {
+ user_name[strlen(user_name)-1] = 0;
}
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
- return (False);
- if (p[32] != ':')
- return (False);
+ if (local_flags & LOCAL_ADD_USER) {
+ SAFE_FREE(new_passwd);
+ new_passwd = smb_xstrdup(user_name);
+ strlower(new_passwd);
+ }
- if (!strncasecmp(p, "NO PASSWORD", 11)) {
- pw_buf.smb_passwd = NULL; /* No password */
- } else {
- if(!gethexpwd(p,smbpwd))
- return False;
- pw_buf.smb_passwd = smbpwd;
+ /*
+ * Now ensure the username ends in '$' for
+ * the machine add.
+ */
+
+ slprintf(buf, sizeof(buf)-1, "%s$", user_name);
+ fstrcpy(user_name, buf);
+ } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
+ static fstring buf;
+
+ if (local_flags & LOCAL_ADD_USER) {
+ /*
+ * Prompt for trusting domain's account password
+ */
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+ if(!new_passwd) {
+ fprintf(stderr, "Unable to get newpassword.\n");
+ exit(1);
+ }
}
+ slprintf(buf, sizeof(buf) - 1, "%s$", user_name);
+ fstrcpy(user_name, buf);
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- pw_buf.smb_nt_passwd = NULL;
- *got_valid_nt_entry = False;
- *valid_old_pwd = True;
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- /* NT Entry was valid - even if 'X' or '*', can be overwritten */
- *got_valid_nt_entry = True;
- if (*p != '*' && *p != 'X') {
- if(gethexpwd(p,smbntpwd))
- pw_buf.smb_nt_passwd = smbntpwd;
+ } else {
+
+ if (remote_machine != NULL) {
+ old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+ }
+
+ if (!(local_flags & LOCAL_SET_PASSWORD)) {
+
+ /*
+ * If we are trying to enable a user, first we need to find out
+ * if they are using a modern version of the smbpasswd file that
+ * disables a user by just writing a flag into the file. If so
+ * then we can re-enable a user without prompting for a new
+ * password. If not (ie. they have a no stored password in the
+ * smbpasswd file) then we need to prompt for a new password.
+ */
+
+ if(local_flags & LOCAL_ENABLE_USER) {
+ SAM_ACCOUNT *sampass = NULL;
+ BOOL ret;
+
+ pdb_init_sam(&sampass);
+ ret = pdb_getsampwnam(sampass, user_name);
+ if((sampass != False) && (pdb_get_lanman_passwd(sampass) == NULL)) {
+ local_flags |= LOCAL_SET_PASSWORD;
+ }
+ pdb_free_sam(&sampass);
}
}
- return &pw_buf;
+
+ if(local_flags & LOCAL_SET_PASSWORD) {
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+
+ if(!new_passwd) {
+ fprintf(stderr, "Unable to get new password.\n");
+ exit(1);
+ }
+ }
+ }
+
+ if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) {
+ fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
+ result = 1;
+ goto done;
+ }
+
+ if(remote_machine) {
+ printf("Password changed for user %s on %s.\n", user_name, remote_machine );
+ } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) {
+ SAM_ACCOUNT *sampass = NULL;
+ BOOL ret;
+
+ pdb_init_sam(&sampass);
+ ret = pdb_getsampwnam(sampass, user_name);
+
+ printf("Password changed for user %s.", user_name );
+ if( (ret != False) && (pdb_get_acct_ctrl(sampass)&ACB_DISABLED) )
+ printf(" User has disabled flag set.");
+ if((ret != False) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) )
+ printf(" User has no password flag set.");
+ printf("\n");
+ pdb_free_sam(&sampass);
}
- return NULL;
+
+ done:
+ SAFE_FREE(new_passwd);
+ return result;
}
-/*
- * Print command usage on stderr and die.
- */
-void
-usage(char *name)
+
+/*************************************************************
+ Handle password changing for non-root.
+*************************************************************/
+
+static int process_nonroot(void)
{
- fprintf(stderr, "Usage is : %s [username]\n", name);
- exit(1);
+ struct passwd *pwd = NULL;
+ int result = 0;
+
+ if (!user_name[0]) {
+ pwd = sys_getpwuid(getuid());
+ if (pwd) {
+ fstrcpy(user_name,pwd->pw_name);
+ } else {
+ fprintf(stderr, "smbpasswd: you don't exist - go away\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * A non-root user is always setting a password
+ * via a remote machine (even if that machine is
+ * localhost).
+ */
+
+ load_interfaces(); /* Delayed from main() */
+
+ if (remote_machine == NULL) {
+ remote_machine = "127.0.0.1";
+ }
+
+ if (remote_machine != NULL) {
+ old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+ }
+
+ if (!new_passwd) {
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+ }
+
+ if (!new_passwd) {
+ fprintf(stderr, "Unable to get new password.\n");
+ exit(1);
+ }
+
+ if (!password_change(remote_machine, user_name, old_passwd, new_passwd, 0)) {
+ fprintf(stderr,"Failed to change password for %s\n", user_name);
+ result = 1;
+ goto done;
+ }
+
+ printf("Password changed for user %s\n", user_name);
+
+ done:
+ SAFE_FREE(old_passwd);
+ SAFE_FREE(new_passwd);
+
+ return result;
}
+
+
+/*********************************************************
+ Start here.
+**********************************************************/
int main(int argc, char **argv)
-{
- int real_uid;
- struct passwd *pwd;
- fstring old_passwd;
- uchar old_p16[16];
- uchar old_nt_p16[16];
- fstring new_passwd;
- uchar new_p16[16];
- uchar new_nt_p16[16];
- char *p;
- struct smb_passwd *smb_pwent;
- FILE *fp;
- BOOL valid_old_pwd = False;
- BOOL got_valid_nt_entry = False;
- long seekpos;
- int pwfd;
- char ascii_p16[66];
- char c;
- int ret, i, err, writelen;
- int lockfd = -1;
- char *pfile = SMB_PASSWD_FILE;
- char readbuf[16 * 1024];
-
- setup_logging(argv[0],True);
-
- charset_initialise();
-
-#ifndef DEBUG_PASSWORD
- /* Check the effective uid */
- if (geteuid() != 0) {
- fprintf(stderr, "%s: Must be setuid root.\n", argv[0]);
- exit(1);
- }
-#endif
-
- /* Get the real uid */
- real_uid = getuid();
-
- /* Deal with usage problems */
- if (real_uid == 0) {
- /* As root we can change anothers password. */
- if (argc != 1 && argc != 2)
- usage(argv[0]);
- } else if (argc != 1)
- usage(argv[0]);
-
-
- if (real_uid == 0 && argc == 2) {
- /* If we are root we can change anothers password. */
- strncpy(user_name, argv[1], sizeof(user_name) - 1);
- user_name[sizeof(user_name) - 1] = '\0';
- pwd = getpwnam(user_name);
- } else {
- pwd = getpwuid(real_uid);
- }
-
- if (pwd == 0) {
- fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]);
- exit(1);
- }
- /* If we are root we don't ask for the old password. */
- old_passwd[0] = '\0';
- if (real_uid != 0) {
- p = getpass("Old SMB password:");
- strncpy(old_passwd, p, sizeof(fstring));
- old_passwd[sizeof(fstring)-1] = '\0';
- }
- new_passwd[0] = '\0';
- p = getpass("New SMB password:");
- strncpy(new_passwd, p, sizeof(fstring));
- new_passwd[sizeof(fstring)-1] = '\0';
- p = getpass("Retype new SMB password:");
- if (strcmp(p, new_passwd)) {
- fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]);
- exit(1);
- }
-
- if (new_passwd[0] == '\0') {
- printf("Password not set\n");
- exit(0);
- }
-
- /* Calculate the MD4 hash (NT compatible) of the old and new passwords */
- memset(old_nt_p16, '\0', 16);
- E_md4hash((uchar *)old_passwd, old_nt_p16);
-
- memset(new_nt_p16, '\0', 16);
- E_md4hash((uchar *) new_passwd, new_nt_p16);
-
- /* Mangle the passwords into Lanman format */
- old_passwd[14] = '\0';
- strupper(old_passwd);
- new_passwd[14] = '\0';
- strupper(new_passwd);
-
- /*
- * Calculate the SMB (lanman) hash functions of both old and new passwords.
- */
-
- memset(old_p16, '\0', 16);
- E_P16((uchar *) old_passwd, old_p16);
-
- memset(new_p16, '\0', 16);
- E_P16((uchar *) new_passwd, new_p16);
-
- /*
- * Open the smbpaswd file XXXX - we need to parse smb.conf to get the
- * filename
- */
- if ((fp = fopen(pfile, "r+")) == NULL) {
- err = errno;
- fprintf(stderr, "%s: Failed to open password file %s.\n",
- argv[0], pfile);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
- /* Set read buffer to 16k for effiecient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- /* make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* Lock the smbpasswd file for write. */
- if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
- err = errno;
- fprintf(stderr, "%s: Failed to lock password file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
- /* Get the smb passwd entry for this user */
- smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd,
- &got_valid_nt_entry, &seekpos);
- if (smb_pwent == NULL) {
- fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
- argv[0], pwd->pw_name, pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* If we are root we don't need to check the old password. */
- if (real_uid != 0) {
- if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) {
- fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Check the old Lanman password */
- if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) {
- fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Check the NT password if it exists */
- if (smb_pwent->smb_nt_passwd != NULL) {
- if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) {
- fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- }
- }
- /*
- * If we get here either we were root or the old password checked out
- * ok.
- */
- /* Create the 32 byte representation of the new p16 */
- for (i = 0; i < 16; i++) {
- sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]);
- }
- if(got_valid_nt_entry) {
- /* Add on the NT md4 hash */
- ascii_p16[32] = ':';
- for (i = 0; i < 16; i++) {
- sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]);
- }
- }
- /*
- * Do an atomic write into the file at the position defined by
- * seekpos.
- */
- pwfd = fileno(fp);
- ret = lseek(pwfd, seekpos - 1, SEEK_SET);
- if (ret != seekpos - 1) {
- err = errno;
- fprintf(stderr, "%s: seek fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Sanity check - ensure the character is a ':' */
- if (read(pwfd, &c, 1) != 1) {
- err = errno;
- fprintf(stderr, "%s: read fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- if (c != ':') {
- fprintf(stderr, "%s: sanity check on passwd file %s failed.\n",
- argv[0], pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- writelen = (got_valid_nt_entry) ? 65 : 32;
- if (write(pwfd, ascii_p16, writelen) != writelen) {
- err = errno;
- fprintf(stderr, "%s: write fail in file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(err);
- }
- fclose(fp);
- pw_file_unlock(lockfd);
- printf("Password changed\n");
- return 0;
-}
+{
+ BOOL amroot = getuid() == 0;
-#else
+ pstrcpy(configfile, dyn_CONFIGFILE);
+ AllowDebugChange = False;
-#include "includes.h"
+#if defined(HAVE_SET_AUTH_PARAMETERS)
+ set_auth_parameters(argc, argv);
+#endif /* HAVE_SET_AUTH_PARAMETERS */
-int
-main(int argc, char **argv)
-{
- printf("smb password encryption not selected in Makefile\n");
- return 0;
+ process_options(argc, argv, amroot);
+
+ setup_logging("smbpasswd", True);
+
+ if (!lp_load(configfile,True,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n",
+ dyn_CONFIGFILE);
+ exit(1);
+ }
+
+ /*
+ * Set the machine NETBIOS name if not already
+ * set from the config file.
+ */
+
+ if (!*global_myname) {
+ char *p;
+ fstrcpy(global_myname, myhostname());
+ p = strchr_m(global_myname, '.' );
+ if (p) *p = 0;
+ }
+ strupper(global_myname);
+
+ /* Check the effective uid - make sure we are not setuid */
+ if (is_setuid_root()) {
+ fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n");
+ exit(1);
+ }
+
+ if (local_mode || amroot) {
+ secrets_init();
+ return process_root();
+ }
+
+ return process_nonroot();
}
-#endif
diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c
new file mode 100644
index 0000000000..b80a27eb37
--- /dev/null
+++ b/source3/utils/smbtree.c
@@ -0,0 +1,423 @@
+/*
+ Unix SMB/CIFS implementation.
+ Network neighbourhood browser.
+
+ Copyright (C) Tim Potter 2000
+
+ 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"
+
+static BOOL use_bcast;
+
+struct user_auth_info {
+ pstring username;
+ pstring password;
+ pstring workgroup;
+};
+
+/* How low can we go? */
+
+enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE};
+enum tree_level level = LEV_SHARE;
+
+static void usage(void)
+{
+ printf(
+"Usage: smbtree [options]\n\
+\n\
+\t-d debuglevel set debug output level\n\
+\t-U username user to autheticate as\n\
+\t-W workgroup workgroup of user to authenticate as\n\
+\t-D list only domains (workgroups) of tree\n\
+\t-S list domains and servers of tree\n\
+\t-b use bcast instead of using the master browser\n\
+\n\
+The username can be of the form username%%password or\n\
+workgroup\\username%%password.\n\n\
+");
+}
+
+/* Holds a list of workgroups or servers */
+
+struct name_list {
+ struct name_list *prev, *next;
+ pstring name, comment;
+ uint32 server_type;
+};
+
+static struct name_list *workgroups, *servers, *shares;
+
+static void free_name_list(struct name_list *list)
+{
+ while(list)
+ DLIST_REMOVE(list, list);
+}
+
+static void add_name(const char *machine_name, uint32 server_type,
+ const char *comment, void *state)
+{
+ struct name_list **name_list = (struct name_list **)state;
+ struct name_list *new_name;
+
+ new_name = (struct name_list *)malloc(sizeof(struct name_list));
+
+ if (!new_name)
+ return;
+
+ ZERO_STRUCTP(new_name);
+
+ pstrcpy(new_name->name, machine_name);
+ pstrcpy(new_name->comment, comment);
+ new_name->server_type = server_type;
+
+ DLIST_ADD(*name_list, new_name);
+}
+
+/* Return a cli_state pointing at the IPC$ share for the given workgroup */
+
+static struct cli_state *get_ipc_connect(char *server,
+ struct user_auth_info *user_info)
+{
+ struct nmb_name calling, called;
+ struct in_addr server_ip;
+ struct cli_state *cli;
+ pstring myname;
+
+ zero_ip(&server_ip);
+
+ get_myname(myname);
+
+ make_nmb_name(&called, myname, 0x0);
+ make_nmb_name(&calling, server, 0x20);
+
+ if (is_ipaddress(server))
+ if (!resolve_name(server, &server_ip, 0x20))
+ return False;
+
+ again:
+ if (!(cli = cli_initialise(NULL))) {
+ DEBUG(4, ("Unable to initialise cli structure\n"));
+ goto error;
+ }
+
+ if (!cli_connect(cli, server, &server_ip)) {
+ DEBUG(4, ("Unable to connect to %s\n", server));
+ goto error;
+ }
+
+ if (!cli_session_request(cli, &calling, &called)) {
+ cli_shutdown(cli);
+ if (!strequal(called.name, "*SMBSERVER")) {
+ make_nmb_name(&called , "*SMBSERVER", 0x20);
+ goto again;
+ }
+ DEBUG(4, ("Session request failed to %s\n", called.name));
+ goto error;
+ }
+
+ if (!cli_negprot(cli)) {
+ DEBUG(4, ("Negprot failed\n"));
+ goto error;
+ }
+
+ if (!cli_session_setup(cli, user_info->username, user_info->password,
+ strlen(user_info->password),
+ user_info->password,
+ strlen(user_info->password), server) &&
+ /* try an anonymous login if it failed */
+ !cli_session_setup(cli, "", "", 1,"", 0, server)) {
+ DEBUG(4, ("Session setup failed\n"));
+ goto error;
+ }
+
+ DEBUG(4,(" session setup ok\n"));
+
+ if (!cli_send_tconX(cli, "IPC$", "?????",
+ user_info->password,
+ strlen(user_info->password)+1)) {
+ DEBUG(4, ("Tconx failed\n"));
+ goto error;
+ }
+
+ return cli;
+
+ /* Clean up after error */
+
+ error:
+ if (cli && cli->initialised)
+ cli_shutdown(cli);
+
+ return NULL;
+}
+
+/* Return the IP address and workgroup of a master browser on the
+ network. */
+
+static BOOL find_master_ip_bcast(pstring workgroup, struct in_addr *server_ip)
+{
+ struct in_addr *ip_list;
+ int i, count;
+
+ /* Go looking for workgroups by broadcasting on the local network */
+
+ if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
+ return False;
+ }
+
+ for (i = 0; i < count; i++) {
+ static fstring name;
+
+ if (!name_status_find("*", 0, 0x1d, ip_list[i], name))
+ continue;
+
+ if (!find_master_ip(name, server_ip))
+ continue;
+
+ pstrcpy(workgroup, name);
+
+ DEBUG(4, ("found master browser %s, %s\n",
+ name, inet_ntoa(ip_list[i])));
+
+ return True;
+ }
+
+ return False;
+}
+
+/****************************************************************************
+ display tree of smb workgroups, servers and shares
+****************************************************************************/
+static BOOL get_workgroups(struct user_auth_info *user_info)
+{
+ struct cli_state *cli;
+ struct in_addr server_ip;
+ pstring master_workgroup;
+
+ /* Try to connect to a #1d name of our current workgroup. If that
+ doesn't work broadcast for a master browser and then jump off
+ that workgroup. */
+
+ pstrcpy(master_workgroup, lp_workgroup());
+
+ if (use_bcast || !find_master_ip(lp_workgroup(), &server_ip)) {
+ DEBUG(4, ("Unable to find master browser for workgroup %s\n",
+ master_workgroup));
+ if (!find_master_ip_bcast(master_workgroup, &server_ip)) {
+ DEBUG(4, ("Unable to find master browser by "
+ "broadcast\n"));
+ return False;
+ }
+ }
+
+ if (!(cli = get_ipc_connect(inet_ntoa(server_ip), user_info)))
+ return False;
+
+ if (!cli_NetServerEnum(cli, master_workgroup,
+ SV_TYPE_DOMAIN_ENUM, add_name, &workgroups))
+ return False;
+
+ return True;
+}
+
+/* Retrieve the list of servers for a given workgroup */
+
+static BOOL get_servers(char *workgroup, struct user_auth_info *user_info)
+{
+ struct cli_state *cli;
+ struct in_addr server_ip;
+
+ /* Open an IPC$ connection to the master browser for the workgroup */
+
+ if (!find_master_ip(workgroup, &server_ip)) {
+ DEBUG(4, ("Cannot find master browser for workgroup %s\n",
+ workgroup));
+ return False;
+ }
+
+ if (!(cli = get_ipc_connect(inet_ntoa(server_ip), user_info)))
+ return False;
+
+ if (!cli_NetServerEnum(cli, workgroup, SV_TYPE_ALL, add_name,
+ &servers))
+ return False;
+
+ return True;
+}
+
+static BOOL get_shares(char *server_name, struct user_auth_info *user_info)
+{
+ struct cli_state *cli;
+
+ if (!(cli = get_ipc_connect(server_name, user_info)))
+ return False;
+
+ if (!cli_RNetShareEnum(cli, add_name, &shares))
+ return False;
+
+ return True;
+}
+
+static BOOL print_tree(struct user_auth_info *user_info)
+{
+ struct name_list *wg, *sv, *sh;
+
+ /* List workgroups */
+
+ if (!get_workgroups(user_info))
+ return False;
+
+ for (wg = workgroups; wg; wg = wg->next) {
+
+ printf("%s\n", wg->name);
+
+ /* List servers */
+
+ free_name_list(servers);
+ servers = NULL;
+
+ if (level == LEV_WORKGROUP ||
+ !get_servers(wg->name, user_info))
+ continue;
+
+ for (sv = servers; sv; sv = sv->next) {
+
+ printf("\t\\\\%-15s\t\t%s\n",
+ sv->name, sv->comment);
+
+ /* List shares */
+
+ free_name_list(shares);
+ shares = NULL;
+
+ if (level == LEV_SERVER ||
+ !get_shares(sv->name, user_info))
+ continue;
+
+ for (sh = shares; sh; sh = sh->next) {
+ printf("\t\t\\\\%s\\%-15s\t%s\n",
+ sv->name, sh->name, sh->comment);
+ }
+ }
+ }
+
+ return True;
+}
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc,char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int opt;
+ char *p;
+ struct user_auth_info user_info;
+ BOOL got_pass = False;
+
+ /* Initialise samba stuff */
+
+ setlinebuf(stdout);
+
+ dbf = x_stderr;
+
+ setup_logging(argv[0],True);
+
+ lp_load(dyn_CONFIGFILE,True,False,False);
+ load_interfaces();
+
+ if (getenv("USER")) {
+ pstrcpy(user_info.username, getenv("USER"));
+
+ if ((p=strchr(user_info.username, '%'))) {
+ *p = 0;
+ pstrcpy(user_info.password, p+1);
+ got_pass = True;
+ memset(strchr(getenv("USER"), '%') + 1, 'X',
+ strlen(user_info.password));
+ }
+ }
+
+ pstrcpy(user_info.workgroup, lp_workgroup());
+
+ /* Parse command line args */
+
+ while ((opt = getopt(argc, argv, "U:hd:W:DSb")) != EOF) {
+ switch (opt) {
+ case 'U':
+ pstrcpy(user_info.username,optarg);
+ p = strchr(user_info.username,'%');
+ if (p) {
+ *p = 0;
+ pstrcpy(user_info.password, p+1);
+ got_pass = 1;
+ }
+ break;
+
+ case 'b':
+ use_bcast = True;
+ break;
+
+ case 'h':
+ usage();
+ exit(1);
+
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+
+ case 'W':
+ pstrcpy(user_info.workgroup, optarg);
+ break;
+
+ case 'D':
+ level = LEV_WORKGROUP;
+ break;
+
+ case 'S':
+ level = LEV_SERVER;
+ break;
+
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ exit(1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ usage();
+ exit(1);
+ }
+
+ if (!got_pass) {
+ char *pass = getpass("Password: ");
+ if (pass) {
+ pstrcpy(user_info.password, pass);
+ }
+ got_pass = True;
+ }
+
+ /* Now do our stuff */
+
+ if (!print_tree(&user_info))
+ return 1;
+
+ return 0;
+}
diff --git a/source3/utils/smbw_sample.c b/source3/utils/smbw_sample.c
new file mode 100644
index 0000000000..5cd792df7a
--- /dev/null
+++ b/source3/utils/smbw_sample.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+static void usage(void)
+{
+ printf("
+smbw_sample - a sample program that uses smbw
+
+smbw_sample <options> path
+
+ options:
+ -W workgroup
+ -l logfile
+ -P prefix
+ -d debuglevel
+ -U username%%password
+ -R resolve order
+
+note that path must start with /smb/
+");
+}
+
+int main(int argc, char *argv[])
+{
+ DIR *dir;
+ struct dirent *dent;
+ int opt;
+ char *p;
+ extern char *optarg;
+ extern int optind;
+ char *path;
+
+ lp_load(dyn_CONFIGFILE,1,0,0);
+ smbw_setup_shared();
+
+ while ((opt = getopt(argc, argv, "W:U:R:d:P:l:hL:")) != EOF) {
+ switch (opt) {
+ case 'W':
+ smbw_setshared("WORKGROUP", optarg);
+ break;
+ case 'l':
+ smbw_setshared("LOGFILE", optarg);
+ break;
+ case 'P':
+ smbw_setshared("PREFIX", optarg);
+ break;
+ case 'd':
+ smbw_setshared("DEBUG", optarg);
+ break;
+ case 'U':
+ p = strchr_m(optarg,'%');
+ if (p) {
+ *p=0;
+ smbw_setshared("PASSWORD",p+1);
+ }
+ smbw_setshared("USER", optarg);
+ break;
+ case 'R':
+ smbw_setshared("RESOLVE_ORDER",optarg);
+ break;
+ case 'h':
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage();
+ exit(1);
+ }
+
+ path = argv[0];
+
+ smbw_init();
+
+ dir = smbw_opendir(path);
+ if (!dir) {
+ printf("failed to open %s\n", path);
+ exit(1);
+ }
+
+ while ((dent = smbw_readdir(dir))) {
+ printf("%s\n", dent->d_name);
+ }
+ smbw_closedir(dir);
+ return 0;
+}
diff --git a/source3/utils/status.c b/source3/utils/status.c
index ed0ae53211..6f4b9eb28c 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -1,8 +1,7 @@
/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
status reporting
- Copyright (C) Andrew Tridgell 1994-1995
+ Copyright (C) Andrew Tridgell 1994-1998
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
@@ -17,242 +16,659 @@
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.
+
+ Revision History:
+
+ 12 aug 96: Erik.Devriendt@te6.siemens.be
+ added support for shared memory implementation of share mode locking
+
+ 21-Jul-1998: rsharpe@ns.aus.com (Richard Sharpe)
+ Added -L (locks only) -S (shares only) flags and code
+
*/
/*
* This program reports current SMB connections
*/
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
+#define NO_SYSLOG
#include "includes.h"
-#include "loadparm.h"
-struct connect_record crec;
-extern int DEBUGLEVEL;
-extern FILE *dbf;
+extern BOOL AllowDebugChange;
+
+struct session_record{
+ pid_t pid;
+ uid_t uid;
+ char machine[31];
+ time_t start;
+ struct session_record *next;
+} *srecs;
static pstring Ucrit_username = ""; /* added by OH */
-int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
-int Ucrit_MaxPid=0; /* added by OH */
-unsigned int Ucrit_IsActive = 0; /* added by OH */
-void Ucrit_addUsername(pstring username); /* added by OH */
-unsigned int Ucrit_checkUsername(pstring username); /* added by OH */
-void Ucrit_addPid(int pid); /* added by OH */
-unsigned int Ucrit_checkPid(int pid); /* added by OH */
-
-int main(int argc, char *argv[])
+static pid_t Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
+static int Ucrit_MaxPid=0; /* added by OH */
+static unsigned int Ucrit_IsActive = 0; /* added by OH */
+static int verbose, brief;
+static int shares_only = 0; /* Added by RJS */
+static int locks_only = 0; /* Added by RJS */
+static BOOL processes_only=False;
+static int show_brl;
+
+/* we need these because we link to locking*.o */
+ void become_root(void) {}
+ void unbecome_root(void) {}
+
+
+/* added by OH */
+static void Ucrit_addUsername(char *username)
+{
+ pstrcpy(Ucrit_username, username);
+ if(strlen(Ucrit_username) > 0)
+ Ucrit_IsActive = 1;
+}
+
+static unsigned int Ucrit_checkUsername(char *username)
+{
+ if ( !Ucrit_IsActive) return 1;
+ if (strcmp(Ucrit_username,username) ==0) return 1;
+ return 0;
+}
+
+static unsigned int Ucrit_checkPid(pid_t pid)
{
- FILE *f;
- pstring fname;
- int uid, c, n;
- static pstring servicesf = CONFIGFILE;
- extern char *optarg;
- int verbose = 0;
- void *dir;
- char *s;
- BOOL firstopen=True;
- BOOL processes_only=False;
- int last_pid=0;
-
- setup_logging(argv[0],True);
-
- charset_initialise();
-
- DEBUGLEVEL = 0;
- dbf = fopen("/dev/null","w");
-
- if (getuid() != geteuid()) {
- printf("smbstatus should not be run setuid\n");
- return(1);
- }
-
- while ((c = getopt(argc, argv, "pdsu:")) != EOF) {
- switch (c) {
- case 'd':
- verbose = 1;
- break;
- case 'p':
- processes_only = 1;
- break;
- case 's':
- strcpy(servicesf, optarg);
- break;
- case 'u': /* added by OH */
- Ucrit_addUsername(optarg); /* added by OH */
- break;
- default:
- fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */
- return (-1);
- }
- }
-
-
-
- if (!lp_load(servicesf,False)) {
- fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
- return (-1);
- }
-
- if (verbose) {
- printf("using configfile = %s\n", servicesf);
- printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL");
- }
-
- strcpy(fname,lp_lockdir());
- standard_sub_basic(fname);
- trim_string(fname,"","/");
- strcat(fname,"/STATUS..LCK");
-
- f = fopen(fname,"r");
- if (!f) {
- printf("Couldn't open status file %s\n",fname);
- if (!lp_status(-1))
- printf("You need to have status=yes in your smb config file\n");
- return(0);
- }
-
- uid = getuid();
-
- if (!processes_only) {
- printf("\nSamba version %s\n",VERSION);
-
- printf("Service uid gid pid machine\n");
- printf("----------------------------------------------\n");
- }
-
- while (!feof(f))
- {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- if ( crec.magic == 0x280267 && process_exists(crec.pid)
- && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */
- )
- {
- Ucrit_addPid(crec.pid); /* added by OH */
- if (processes_only) {
- if (last_pid != crec.pid)
- printf("%d\n",crec.pid);
- last_pid = crec.pid; /* XXXX we can still get repeats, have to
- add a sort at some time */
+ int i;
+ if ( !Ucrit_IsActive) return 1;
+ for (i=0;i<Ucrit_MaxPid;i++)
+ if( pid == Ucrit_pid[i] ) return 1;
+ return 0;
+}
+
+
+static void print_share_mode(share_mode_entry *e, char *fname)
+{
+ static int count;
+ if (count==0) {
+ d_printf("Locked files:\n");
+ d_printf("Pid DenyMode Access R/W Oplock Name\n");
+ d_printf("--------------------------------------------------------------\n");
+ }
+ count++;
+
+ if (Ucrit_checkPid(e->pid)) {
+ d_printf("%-5d ",(int)e->pid);
+ switch (GET_DENY_MODE(e->share_mode)) {
+ case DENY_NONE: d_printf("DENY_NONE "); break;
+ case DENY_ALL: d_printf("DENY_ALL "); break;
+ case DENY_DOS: d_printf("DENY_DOS "); break;
+ case DENY_READ: d_printf("DENY_READ "); break;
+ case DENY_WRITE:printf("DENY_WRITE "); break;
+ case DENY_FCB: d_printf("DENY_FCB "); break;
+ }
+ d_printf("0x%-8x ",(unsigned int)e->desired_access);
+ switch (e->share_mode&0xF) {
+ case 0: d_printf("RDONLY "); break;
+ case 1: d_printf("WRONLY "); break;
+ case 2: d_printf("RDWR "); break;
+ }
+
+ if((e->op_type &
+ (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
+ (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
+ d_printf("EXCLUSIVE+BATCH ");
+ else if (e->op_type & EXCLUSIVE_OPLOCK)
+ d_printf("EXCLUSIVE ");
+ else if (e->op_type & BATCH_OPLOCK)
+ d_printf("BATCH ");
+ else if (e->op_type & LEVEL_II_OPLOCK)
+ d_printf("LEVEL_II ");
+ else
+ d_printf("NONE ");
+
+ d_printf(" %s %s",fname,
+ asctime(LocalTime((time_t *)&e->time.tv_sec)));
}
- else
- printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
- crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
- crec.machine,crec.addr,
- asctime(LocalTime(&crec.start,GMT_TO_LOCAL)));
- }
- }
- fclose(f);
-
- if (processes_only) exit(0);
-
- printf("\n");
-
- dir = opendir(lp_lockdir());
- if (!dir) return(0);
- while ((s=readdirname(dir))) {
- char buf[16];
- int pid,mode;
- time_t t;
- int fd;
- pstring lname;
- int dev,inode;
-
- if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
-
- strcpy(lname,lp_lockdir());
- trim_string(lname,NULL,"/");
- strcat(lname,"/");
- strcat(lname,s);
-
- fd = open(lname,O_RDONLY,0);
- if (fd < 0) continue;
- if (read(fd,buf,16) != 16) continue;
- n = read(fd,fname,sizeof(fname));
- fname[MAX(n,0)]=0;
- close(fd);
-
- t = IVAL(buf,0);
- mode = IVAL(buf,4);
- pid = IVAL(buf,8);
-
- if ( !Ucrit_checkPid(pid) ) /* added by OH */
- continue;
-
- if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
- if (unlink(lname)==0)
- printf("Deleted stale share file %s\n",s);
- continue;
- }
-
- fname[sizeof(fname)-1] = 0;
-
- if (firstopen) {
- firstopen=False;
- printf("Locked files:\n");
- printf("Pid DenyMode R/W Name\n");
- printf("------------------------------\n");
- }
-
-
- printf("%-5d ",pid);
- switch ((mode>>4)&0xF)
- {
- case DENY_NONE: printf("DENY_NONE "); break;
- case DENY_ALL: printf("DENY_ALL "); break;
- case DENY_DOS: printf("DENY_DOS "); break;
- case DENY_READ: printf("DENY_READ "); break;
- case DENY_WRITE:printf("DENY_WRITE "); break;
- }
- switch (mode&0xF)
- {
- case 0: printf("RDONLY "); break;
- case 1: printf("WRONLY "); break;
- case 2: printf("RDWR "); break;
- }
- printf(" %s %s",fname,asctime(LocalTime(&t,GMT_TO_LOCAL)));
- }
- closedir(dir);
-
- if (firstopen)
- printf("No locked files\n");
-
- return (0);
}
-/* added by OH */
-void Ucrit_addUsername(pstring username)
+static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid,
+ enum brl_type lock_type,
+ br_off start, br_off size)
{
- strcpy(Ucrit_username, username);
- if(strlen(Ucrit_username) > 0)
- Ucrit_IsActive = 1;
+ static int count;
+ if (count==0) {
+ d_printf("Byte range locks:\n");
+ d_printf(" Pid dev:inode R/W start size\n");
+ d_printf("------------------------------------------------\n");
+ }
+ count++;
+
+ d_printf("%6d %05x:%05x %s %9.0f %9.0f\n",
+ (int)pid, (int)dev, (int)ino,
+ lock_type==READ_LOCK?"R":"W",
+ (double)start, (double)size);
}
-unsigned int Ucrit_checkUsername(pstring username)
+
+/*******************************************************************
+ dump the elements of the profile structure
+ ******************************************************************/
+static int profile_dump(void)
{
- if ( !Ucrit_IsActive) return 1;
- if (strcmp(Ucrit_username,username) ==0) return 1;
- return 0;
+ if (!profile_setup(True)) {
+ fprintf(stderr,"Failed to initialise profile memory\n");
+ return -1;
+ }
+
+ d_printf("smb_count: %u\n", profile_p->smb_count);
+ d_printf("uid_changes: %u\n", profile_p->uid_changes);
+ d_printf("************************ System Calls ****************************\n");
+ d_printf("opendir_count: %u\n", profile_p->syscall_opendir_count);
+ d_printf("opendir_time: %u\n", profile_p->syscall_opendir_time);
+ d_printf("readdir_count: %u\n", profile_p->syscall_readdir_count);
+ d_printf("readdir_time: %u\n", profile_p->syscall_readdir_time);
+ d_printf("mkdir_count: %u\n", profile_p->syscall_mkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->syscall_mkdir_time);
+ d_printf("rmdir_count: %u\n", profile_p->syscall_rmdir_count);
+ d_printf("rmdir_time: %u\n", profile_p->syscall_rmdir_time);
+ d_printf("closedir_count: %u\n", profile_p->syscall_closedir_count);
+ d_printf("closedir_time: %u\n", profile_p->syscall_closedir_time);
+ d_printf("open_count: %u\n", profile_p->syscall_open_count);
+ d_printf("open_time: %u\n", profile_p->syscall_open_time);
+ d_printf("close_count: %u\n", profile_p->syscall_close_count);
+ d_printf("close_time: %u\n", profile_p->syscall_close_time);
+ d_printf("read_count: %u\n", profile_p->syscall_read_count);
+ d_printf("read_time: %u\n", profile_p->syscall_read_time);
+ d_printf("read_bytes: %u\n", profile_p->syscall_read_bytes);
+ d_printf("write_count: %u\n", profile_p->syscall_write_count);
+ d_printf("write_time: %u\n", profile_p->syscall_write_time);
+ d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes);
+ d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count);
+ d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time);
+ d_printf("rename_count: %u\n", profile_p->syscall_rename_count);
+ d_printf("rename_time: %u\n", profile_p->syscall_rename_time);
+ d_printf("fsync_count: %u\n", profile_p->syscall_fsync_count);
+ d_printf("fsync_time: %u\n", profile_p->syscall_fsync_time);
+ d_printf("stat_count: %u\n", profile_p->syscall_stat_count);
+ d_printf("stat_time: %u\n", profile_p->syscall_stat_time);
+ d_printf("fstat_count: %u\n", profile_p->syscall_fstat_count);
+ d_printf("fstat_time: %u\n", profile_p->syscall_fstat_time);
+ d_printf("lstat_count: %u\n", profile_p->syscall_lstat_count);
+ d_printf("lstat_time: %u\n", profile_p->syscall_lstat_time);
+ d_printf("unlink_count: %u\n", profile_p->syscall_unlink_count);
+ d_printf("unlink_time: %u\n", profile_p->syscall_unlink_time);
+ d_printf("chmod_count: %u\n", profile_p->syscall_chmod_count);
+ d_printf("chmod_time: %u\n", profile_p->syscall_chmod_time);
+ d_printf("fchmod_count: %u\n", profile_p->syscall_fchmod_count);
+ d_printf("fchmod_time: %u\n", profile_p->syscall_fchmod_time);
+ d_printf("chown_count: %u\n", profile_p->syscall_chown_count);
+ d_printf("chown_time: %u\n", profile_p->syscall_chown_time);
+ d_printf("fchown_count: %u\n", profile_p->syscall_fchown_count);
+ d_printf("fchown_time: %u\n", profile_p->syscall_fchown_time);
+ d_printf("chdir_count: %u\n", profile_p->syscall_chdir_count);
+ d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time);
+ d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count);
+ d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time);
+ d_printf("utime_count: %u\n", profile_p->syscall_utime_count);
+ d_printf("utime_time: %u\n", profile_p->syscall_utime_time);
+ d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count);
+ d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time);
+ d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count);
+ d_printf("fcntl_lock_time: %u\n", profile_p->syscall_fcntl_lock_time);
+ d_printf("readlink_count: %u\n", profile_p->syscall_readlink_count);
+ d_printf("readlink_time: %u\n", profile_p->syscall_readlink_time);
+ d_printf("symlink_count: %u\n", profile_p->syscall_symlink_count);
+ d_printf("symlink_time: %u\n", profile_p->syscall_symlink_time);
+ d_printf("************************ Statcache *******************************\n");
+ d_printf("lookups: %u\n", profile_p->statcache_lookups);
+ d_printf("misses: %u\n", profile_p->statcache_misses);
+ d_printf("hits: %u\n", profile_p->statcache_hits);
+ d_printf("************************ Writecache ******************************\n");
+ d_printf("read_hits: %u\n", profile_p->writecache_read_hits);
+ d_printf("abutted_writes: %u\n", profile_p->writecache_abutted_writes);
+ d_printf("total_writes: %u\n", profile_p->writecache_total_writes);
+ d_printf("non_oplock_writes: %u\n", profile_p->writecache_non_oplock_writes);
+ d_printf("direct_writes: %u\n", profile_p->writecache_direct_writes);
+ d_printf("init_writes: %u\n", profile_p->writecache_init_writes);
+ d_printf("flushed_writes[SEEK]: %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]);
+ d_printf("flushed_writes[READ]: %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]);
+ d_printf("flushed_writes[WRITE]: %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]);
+ d_printf("flushed_writes[READRAW]: %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]);
+ d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]);
+ d_printf("flushed_writes[CLOSE]: %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]);
+ d_printf("flushed_writes[SYNC]: %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]);
+ d_printf("flushed_writes[SIZECHANGE]: %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]);
+ d_printf("num_perfect_writes: %u\n", profile_p->writecache_num_perfect_writes);
+ d_printf("num_write_caches: %u\n", profile_p->writecache_num_write_caches);
+ d_printf("allocated_write_caches: %u\n", profile_p->writecache_allocated_write_caches);
+ d_printf("************************ SMB Calls *******************************\n");
+ d_printf("mkdir_count: %u\n", profile_p->SMBmkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->SMBmkdir_time);
+ d_printf("rmdir_count: %u\n", profile_p->SMBrmdir_count);
+ d_printf("rmdir_time: %u\n", profile_p->SMBrmdir_time);
+ d_printf("open_count: %u\n", profile_p->SMBopen_count);
+ d_printf("open_time: %u\n", profile_p->SMBopen_time);
+ d_printf("create_count: %u\n", profile_p->SMBcreate_count);
+ d_printf("create_time: %u\n", profile_p->SMBcreate_time);
+ d_printf("close_count: %u\n", profile_p->SMBclose_count);
+ d_printf("close_time: %u\n", profile_p->SMBclose_time);
+ d_printf("flush_count: %u\n", profile_p->SMBflush_count);
+ d_printf("flush_time: %u\n", profile_p->SMBflush_time);
+ d_printf("unlink_count: %u\n", profile_p->SMBunlink_count);
+ d_printf("unlink_time: %u\n", profile_p->SMBunlink_time);
+ d_printf("mv_count: %u\n", profile_p->SMBmv_count);
+ d_printf("mv_time: %u\n", profile_p->SMBmv_time);
+ d_printf("getatr_count: %u\n", profile_p->SMBgetatr_count);
+ d_printf("getatr_time: %u\n", profile_p->SMBgetatr_time);
+ d_printf("setatr_count: %u\n", profile_p->SMBsetatr_count);
+ d_printf("setatr_time: %u\n", profile_p->SMBsetatr_time);
+ d_printf("read_count: %u\n", profile_p->SMBread_count);
+ d_printf("read_time: %u\n", profile_p->SMBread_time);
+ d_printf("write_count: %u\n", profile_p->SMBwrite_count);
+ d_printf("write_time: %u\n", profile_p->SMBwrite_time);
+ d_printf("lock_count: %u\n", profile_p->SMBlock_count);
+ d_printf("lock_time: %u\n", profile_p->SMBlock_time);
+ d_printf("unlock_count: %u\n", profile_p->SMBunlock_count);
+ d_printf("unlock_time: %u\n", profile_p->SMBunlock_time);
+ d_printf("ctemp_count: %u\n", profile_p->SMBctemp_count);
+ d_printf("ctemp_time: %u\n", profile_p->SMBctemp_time);
+ d_printf("mknew_count: %u\n", profile_p->SMBmknew_count);
+ d_printf("mknew_time: %u\n", profile_p->SMBmknew_time);
+ d_printf("chkpth_count: %u\n", profile_p->SMBchkpth_count);
+ d_printf("chkpth_time: %u\n", profile_p->SMBchkpth_time);
+ d_printf("exit_count: %u\n", profile_p->SMBexit_count);
+ d_printf("exit_time: %u\n", profile_p->SMBexit_time);
+ d_printf("lseek_count: %u\n", profile_p->SMBlseek_count);
+ d_printf("lseek_time: %u\n", profile_p->SMBlseek_time);
+ d_printf("lockread_count: %u\n", profile_p->SMBlockread_count);
+ d_printf("lockread_time: %u\n", profile_p->SMBlockread_time);
+ d_printf("writeunlock_count: %u\n", profile_p->SMBwriteunlock_count);
+ d_printf("writeunlock_time: %u\n", profile_p->SMBwriteunlock_time);
+ d_printf("readbraw_count: %u\n", profile_p->SMBreadbraw_count);
+ d_printf("readbraw_time: %u\n", profile_p->SMBreadbraw_time);
+ d_printf("readBmpx_count: %u\n", profile_p->SMBreadBmpx_count);
+ d_printf("readBmpx_time: %u\n", profile_p->SMBreadBmpx_time);
+ d_printf("readBs_count: %u\n", profile_p->SMBreadBs_count);
+ d_printf("readBs_time: %u\n", profile_p->SMBreadBs_time);
+ d_printf("writebraw_count: %u\n", profile_p->SMBwritebraw_count);
+ d_printf("writebraw_time: %u\n", profile_p->SMBwritebraw_time);
+ d_printf("writeBmpx_count: %u\n", profile_p->SMBwriteBmpx_count);
+ d_printf("writeBmpx_time: %u\n", profile_p->SMBwriteBmpx_time);
+ d_printf("writeBs_count: %u\n", profile_p->SMBwriteBs_count);
+ d_printf("writeBs_time: %u\n", profile_p->SMBwriteBs_time);
+ d_printf("writec_count: %u\n", profile_p->SMBwritec_count);
+ d_printf("writec_time: %u\n", profile_p->SMBwritec_time);
+ d_printf("setattrE_count: %u\n", profile_p->SMBsetattrE_count);
+ d_printf("setattrE_time: %u\n", profile_p->SMBsetattrE_time);
+ d_printf("getattrE_count: %u\n", profile_p->SMBgetattrE_count);
+ d_printf("getattrE_time: %u\n", profile_p->SMBgetattrE_time);
+ d_printf("lockingX_count: %u\n", profile_p->SMBlockingX_count);
+ d_printf("lockingX_time: %u\n", profile_p->SMBlockingX_time);
+ d_printf("trans_count: %u\n", profile_p->SMBtrans_count);
+ d_printf("trans_time: %u\n", profile_p->SMBtrans_time);
+ d_printf("transs_count: %u\n", profile_p->SMBtranss_count);
+ d_printf("transs_time: %u\n", profile_p->SMBtranss_time);
+ d_printf("ioctl_count: %u\n", profile_p->SMBioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->SMBioctl_time);
+ d_printf("ioctls_count: %u\n", profile_p->SMBioctls_count);
+ d_printf("ioctls_time: %u\n", profile_p->SMBioctls_time);
+ d_printf("copy_count: %u\n", profile_p->SMBcopy_count);
+ d_printf("copy_time: %u\n", profile_p->SMBcopy_time);
+ d_printf("move_count: %u\n", profile_p->SMBmove_count);
+ d_printf("move_time: %u\n", profile_p->SMBmove_time);
+ d_printf("echo_count: %u\n", profile_p->SMBecho_count);
+ d_printf("echo_time: %u\n", profile_p->SMBecho_time);
+ d_printf("writeclose_count: %u\n", profile_p->SMBwriteclose_count);
+ d_printf("writeclose_time: %u\n", profile_p->SMBwriteclose_time);
+ d_printf("openX_count: %u\n", profile_p->SMBopenX_count);
+ d_printf("openX_time: %u\n", profile_p->SMBopenX_time);
+ d_printf("readX_count: %u\n", profile_p->SMBreadX_count);
+ d_printf("readX_time: %u\n", profile_p->SMBreadX_time);
+ d_printf("writeX_count: %u\n", profile_p->SMBwriteX_count);
+ d_printf("writeX_time: %u\n", profile_p->SMBwriteX_time);
+ d_printf("trans2_count: %u\n", profile_p->SMBtrans2_count);
+ d_printf("trans2_time: %u\n", profile_p->SMBtrans2_time);
+ d_printf("transs2_count: %u\n", profile_p->SMBtranss2_count);
+ d_printf("transs2_time: %u\n", profile_p->SMBtranss2_time);
+ d_printf("findclose_count: %u\n", profile_p->SMBfindclose_count);
+ d_printf("findclose_time: %u\n", profile_p->SMBfindclose_time);
+ d_printf("findnclose_count: %u\n", profile_p->SMBfindnclose_count);
+ d_printf("findnclose_time: %u\n", profile_p->SMBfindnclose_time);
+ d_printf("tcon_count: %u\n", profile_p->SMBtcon_count);
+ d_printf("tcon_time: %u\n", profile_p->SMBtcon_time);
+ d_printf("tdis_count: %u\n", profile_p->SMBtdis_count);
+ d_printf("tdis_time: %u\n", profile_p->SMBtdis_time);
+ d_printf("negprot_count: %u\n", profile_p->SMBnegprot_count);
+ d_printf("negprot_time: %u\n", profile_p->SMBnegprot_time);
+ d_printf("sesssetupX_count: %u\n", profile_p->SMBsesssetupX_count);
+ d_printf("sesssetupX_time: %u\n", profile_p->SMBsesssetupX_time);
+ d_printf("ulogoffX_count: %u\n", profile_p->SMBulogoffX_count);
+ d_printf("ulogoffX_time: %u\n", profile_p->SMBulogoffX_time);
+ d_printf("tconX_count: %u\n", profile_p->SMBtconX_count);
+ d_printf("tconX_time: %u\n", profile_p->SMBtconX_time);
+ d_printf("dskattr_count: %u\n", profile_p->SMBdskattr_count);
+ d_printf("dskattr_time: %u\n", profile_p->SMBdskattr_time);
+ d_printf("search_count: %u\n", profile_p->SMBsearch_count);
+ d_printf("search_time: %u\n", profile_p->SMBsearch_time);
+ d_printf("ffirst_count: %u\n", profile_p->SMBffirst_count);
+ d_printf("ffirst_time: %u\n", profile_p->SMBffirst_time);
+ d_printf("funique_count: %u\n", profile_p->SMBfunique_count);
+ d_printf("funique_time: %u\n", profile_p->SMBfunique_time);
+ d_printf("fclose_count: %u\n", profile_p->SMBfclose_count);
+ d_printf("fclose_time: %u\n", profile_p->SMBfclose_time);
+ d_printf("nttrans_count: %u\n", profile_p->SMBnttrans_count);
+ d_printf("nttrans_time: %u\n", profile_p->SMBnttrans_time);
+ d_printf("nttranss_count: %u\n", profile_p->SMBnttranss_count);
+ d_printf("nttranss_time: %u\n", profile_p->SMBnttranss_time);
+ d_printf("ntcreateX_count: %u\n", profile_p->SMBntcreateX_count);
+ d_printf("ntcreateX_time: %u\n", profile_p->SMBntcreateX_time);
+ d_printf("ntcancel_count: %u\n", profile_p->SMBntcancel_count);
+ d_printf("ntcancel_time: %u\n", profile_p->SMBntcancel_time);
+ d_printf("splopen_count: %u\n", profile_p->SMBsplopen_count);
+ d_printf("splopen_time: %u\n", profile_p->SMBsplopen_time);
+ d_printf("splwr_count: %u\n", profile_p->SMBsplwr_count);
+ d_printf("splwr_time: %u\n", profile_p->SMBsplwr_time);
+ d_printf("splclose_count: %u\n", profile_p->SMBsplclose_count);
+ d_printf("splclose_time: %u\n", profile_p->SMBsplclose_time);
+ d_printf("splretq_count: %u\n", profile_p->SMBsplretq_count);
+ d_printf("splretq_time: %u\n", profile_p->SMBsplretq_time);
+ d_printf("sends_count: %u\n", profile_p->SMBsends_count);
+ d_printf("sends_time: %u\n", profile_p->SMBsends_time);
+ d_printf("sendb_count: %u\n", profile_p->SMBsendb_count);
+ d_printf("sendb_time: %u\n", profile_p->SMBsendb_time);
+ d_printf("fwdname_count: %u\n", profile_p->SMBfwdname_count);
+ d_printf("fwdname_time: %u\n", profile_p->SMBfwdname_time);
+ d_printf("cancelf_count: %u\n", profile_p->SMBcancelf_count);
+ d_printf("cancelf_time: %u\n", profile_p->SMBcancelf_time);
+ d_printf("getmac_count: %u\n", profile_p->SMBgetmac_count);
+ d_printf("getmac_time: %u\n", profile_p->SMBgetmac_time);
+ d_printf("sendstrt_count: %u\n", profile_p->SMBsendstrt_count);
+ d_printf("sendstrt_time: %u\n", profile_p->SMBsendstrt_time);
+ d_printf("sendend_count: %u\n", profile_p->SMBsendend_count);
+ d_printf("sendend_time: %u\n", profile_p->SMBsendend_time);
+ d_printf("sendtxt_count: %u\n", profile_p->SMBsendtxt_count);
+ d_printf("sendtxt_time: %u\n", profile_p->SMBsendtxt_time);
+ d_printf("invalid_count: %u\n", profile_p->SMBinvalid_count);
+ d_printf("invalid_time: %u\n", profile_p->SMBinvalid_time);
+ d_printf("************************ Pathworks Calls *************************\n");
+ d_printf("setdir_count: %u\n", profile_p->pathworks_setdir_count);
+ d_printf("setdir_time: %u\n", profile_p->pathworks_setdir_time);
+ d_printf("************************ Trans2 Calls ****************************\n");
+ d_printf("open_count: %u\n", profile_p->Trans2_open_count);
+ d_printf("open_time: %u\n", profile_p->Trans2_open_time);
+ d_printf("findfirst_count: %u\n", profile_p->Trans2_findfirst_count);
+ d_printf("findfirst_time: %u\n", profile_p->Trans2_findfirst_time);
+ d_printf("findnext_count: %u\n", profile_p->Trans2_findnext_count);
+ d_printf("findnext_time: %u\n", profile_p->Trans2_findnext_time);
+ d_printf("qfsinfo_count: %u\n", profile_p->Trans2_qfsinfo_count);
+ d_printf("qfsinfo_time: %u\n", profile_p->Trans2_qfsinfo_time);
+ d_printf("setfsinfo_count: %u\n", profile_p->Trans2_setfsinfo_count);
+ d_printf("setfsinfo_time: %u\n", profile_p->Trans2_setfsinfo_time);
+ d_printf("qpathinfo_count: %u\n", profile_p->Trans2_qpathinfo_count);
+ d_printf("qpathinfo_time: %u\n", profile_p->Trans2_qpathinfo_time);
+ d_printf("setpathinfo_count: %u\n", profile_p->Trans2_setpathinfo_count);
+ d_printf("setpathinfo_time: %u\n", profile_p->Trans2_setpathinfo_time);
+ d_printf("qfileinfo_count: %u\n", profile_p->Trans2_qfileinfo_count);
+ d_printf("qfileinfo_time: %u\n", profile_p->Trans2_qfileinfo_time);
+ d_printf("setfileinfo_count: %u\n", profile_p->Trans2_setfileinfo_count);
+ d_printf("setfileinfo_time: %u\n", profile_p->Trans2_setfileinfo_time);
+ d_printf("fsctl_count: %u\n", profile_p->Trans2_fsctl_count);
+ d_printf("fsctl_time: %u\n", profile_p->Trans2_fsctl_time);
+ d_printf("ioctl_count: %u\n", profile_p->Trans2_ioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->Trans2_ioctl_time);
+ d_printf("findnotifyfirst_count: %u\n", profile_p->Trans2_findnotifyfirst_count);
+ d_printf("findnotifyfirst_time: %u\n", profile_p->Trans2_findnotifyfirst_time);
+ d_printf("findnotifynext_count: %u\n", profile_p->Trans2_findnotifynext_count);
+ d_printf("findnotifynext_time: %u\n", profile_p->Trans2_findnotifynext_time);
+ d_printf("mkdir_count: %u\n", profile_p->Trans2_mkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->Trans2_mkdir_time);
+ d_printf("session_setup_count: %u\n", profile_p->Trans2_session_setup_count);
+ d_printf("session_setup_time: %u\n", profile_p->Trans2_session_setup_time);
+ d_printf("get_dfs_referral_count: %u\n", profile_p->Trans2_get_dfs_referral_count);
+ d_printf("get_dfs_referral_time: %u\n", profile_p->Trans2_get_dfs_referral_time);
+ d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count);
+ d_printf("report_dfs_inconsistancy_time: %u\n", profile_p->Trans2_report_dfs_inconsistancy_time);
+ d_printf("************************ NT Transact Calls ***********************\n");
+ d_printf("create_count: %u\n", profile_p->NT_transact_create_count);
+ d_printf("create_time: %u\n", profile_p->NT_transact_create_time);
+ d_printf("ioctl_count: %u\n", profile_p->NT_transact_ioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->NT_transact_ioctl_time);
+ d_printf("set_security_desc_count: %u\n", profile_p->NT_transact_set_security_desc_count);
+ d_printf("set_security_desc_time: %u\n", profile_p->NT_transact_set_security_desc_time);
+ d_printf("notify_change_count: %u\n", profile_p->NT_transact_notify_change_count);
+ d_printf("notify_change_time: %u\n", profile_p->NT_transact_notify_change_time);
+ d_printf("rename_count: %u\n", profile_p->NT_transact_rename_count);
+ d_printf("rename_time: %u\n", profile_p->NT_transact_rename_time);
+ d_printf("query_security_desc_count: %u\n", profile_p->NT_transact_query_security_desc_count);
+ d_printf("query_security_desc_time: %u\n", profile_p->NT_transact_query_security_desc_time);
+ d_printf("************************ ACL Calls *******************************\n");
+ d_printf("get_nt_acl_count: %u\n", profile_p->get_nt_acl_count);
+ d_printf("get_nt_acl_time: %u\n", profile_p->get_nt_acl_time);
+ d_printf("fget_nt_acl_count: %u\n", profile_p->fget_nt_acl_count);
+ d_printf("fget_nt_acl_time: %u\n", profile_p->fget_nt_acl_time);
+ d_printf("set_nt_acl_count: %u\n", profile_p->set_nt_acl_count);
+ d_printf("set_nt_acl_time: %u\n", profile_p->set_nt_acl_time);
+ d_printf("fset_nt_acl_count: %u\n", profile_p->fset_nt_acl_count);
+ d_printf("fset_nt_acl_time: %u\n", profile_p->fset_nt_acl_time);
+ d_printf("chmod_acl_count: %u\n", profile_p->chmod_acl_count);
+ d_printf("chmod_acl_time: %u\n", profile_p->chmod_acl_time);
+ d_printf("fchmod_acl_count: %u\n", profile_p->fchmod_acl_count);
+ d_printf("fchmod_acl_time: %u\n", profile_p->fchmod_acl_time);
+ d_printf("************************ NMBD Calls ****************************\n");
+ d_printf("name_release_count: %u\n", profile_p->name_release_count);
+ d_printf("name_release_time: %u\n", profile_p->name_release_time);
+ d_printf("name_refresh_count: %u\n", profile_p->name_refresh_count);
+ d_printf("name_refresh_time: %u\n", profile_p->name_refresh_time);
+ d_printf("name_registration_count: %u\n", profile_p->name_registration_count);
+ d_printf("name_registration_time: %u\n", profile_p->name_registration_time);
+ d_printf("node_status_count: %u\n", profile_p->node_status_count);
+ d_printf("node_status_time: %u\n", profile_p->node_status_time);
+ d_printf("name_query_count: %u\n", profile_p->name_query_count);
+ d_printf("name_query_time: %u\n", profile_p->name_query_time);
+ d_printf("host_announce_count: %u\n", profile_p->host_announce_count);
+ d_printf("host_announce_time: %u\n", profile_p->host_announce_time);
+ d_printf("workgroup_announce_count: %u\n", profile_p->workgroup_announce_count);
+ d_printf("workgroup_announce_time: %u\n", profile_p->workgroup_announce_time);
+ d_printf("local_master_announce_count: %u\n", profile_p->local_master_announce_count);
+ d_printf("local_master_announce_time: %u\n", profile_p->local_master_announce_time);
+ d_printf("master_browser_announce_count: %u\n", profile_p->master_browser_announce_count);
+ d_printf("master_browser_announce_time: %u\n", profile_p->master_browser_announce_time);
+ d_printf("lm_host_announce_count: %u\n", profile_p->lm_host_announce_count);
+ d_printf("lm_host_announce_time: %u\n", profile_p->lm_host_announce_time);
+ d_printf("get_backup_list_count: %u\n", profile_p->get_backup_list_count);
+ d_printf("get_backup_list_time: %u\n", profile_p->get_backup_list_time);
+ d_printf("reset_browser_count: %u\n", profile_p->reset_browser_count);
+ d_printf("reset_browser_time: %u\n", profile_p->reset_browser_time);
+ d_printf("announce_request_count: %u\n", profile_p->announce_request_count);
+ d_printf("announce_request_time: %u\n", profile_p->announce_request_time);
+ d_printf("lm_announce_request_count: %u\n", profile_p->lm_announce_request_count);
+ d_printf("lm_announce_request_time: %u\n", profile_p->lm_announce_request_time);
+ d_printf("domain_logon_count: %u\n", profile_p->domain_logon_count);
+ d_printf("domain_logon_time: %u\n", profile_p->domain_logon_time);
+ d_printf("sync_browse_lists_count: %u\n", profile_p->sync_browse_lists_count);
+ d_printf("sync_browse_lists_time: %u\n", profile_p->sync_browse_lists_time);
+ d_printf("run_elections_count: %u\n", profile_p->run_elections_count);
+ d_printf("run_elections_time: %u\n", profile_p->run_elections_time);
+ d_printf("election_count: %u\n", profile_p->election_count);
+ d_printf("election_time: %u\n", profile_p->election_time);
+
+ return 0;
}
-void Ucrit_addPid(int pid)
+
+static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
- int i;
- if ( !Ucrit_IsActive) return;
- for (i=0;i<Ucrit_MaxPid;i++)
- if( pid == Ucrit_pid[i] ) return;
- Ucrit_pid[Ucrit_MaxPid++] = pid;
+ struct connections_data crec;
+
+ if (dbuf.dsize != sizeof(crec))
+ return 0;
+
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum == -1)
+ return 0;
+
+ if (!process_exists(crec.pid) || !Ucrit_checkUsername(uidtoname(crec.uid))) {
+ return 0;
+ }
+
+ d_printf("%-10.10s %5d %-12s %s",
+ crec.name,(int)crec.pid,
+ crec.machine,
+ asctime(LocalTime(&crec.start)));
+
+ return 0;
}
-unsigned int Ucrit_checkPid(int pid)
+static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
- int i;
- if ( !Ucrit_IsActive) return 1;
- for (i=0;i<Ucrit_MaxPid;i++)
- if( pid == Ucrit_pid[i] ) return 1;
- return 0;
+ struct sessionid sessionid;
+
+ if (dbuf.dsize != sizeof(sessionid))
+ return 0;
+
+ memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
+
+ if (!process_exists(sessionid.pid) || !Ucrit_checkUsername(uidtoname(sessionid.uid))) {
+ return 0;
+ }
+
+ d_printf("%5d %-12s %-12s %-12s (%s)\n",
+ (int)sessionid.pid, uidtoname(sessionid.uid), gidtoname(sessionid.gid),
+ sessionid.remote_machine, sessionid.hostname);
+
+ return 0;
}
+
+
+
+ int main(int argc, char *argv[])
+{
+ pstring fname;
+ int c;
+ static int profile_only = 0;
+ static int new_debuglevel = -1;
+ TDB_CONTEXT *tdb;
+ poptContext pc;
+ struct poptOption long_options[] = {
+ {"processes", 'p', POPT_ARG_NONE, &processes_only},
+ {"verbose", 'v', POPT_ARG_NONE, &verbose},
+ {"locks", 'L', POPT_ARG_NONE, &locks_only},
+ {"shares", 'S', POPT_ARG_NONE, &shares_only},
+ {"conf", 's', POPT_ARG_STRING, 0, 's'},
+ {"user", 'u', POPT_ARG_STRING, 0, 'u'},
+ {"brief", 'b', POPT_ARG_NONE, &brief},
+ {"profile", 'P', POPT_ARG_NONE, &profile_only},
+ {"byterange", 'B', POPT_ARG_NONE, &show_brl},
+ {"debug", 'd', POPT_ARG_INT, &new_debuglevel},
+ { 0, 0, 0, 0}
+ };
+
+
+ setup_logging(argv[0],True);
+
+ AllowDebugChange = False;
+ DEBUGLEVEL = 0;
+ dbf = x_stderr;
+
+ if (getuid() != geteuid()) {
+ d_printf("smbstatus should not be run setuid\n");
+ return(1);
+ }
+
+ pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ while ((c = poptGetNextOpt(pc)) != EOF) {
+ switch (c) {
+ case 's':
+ pstrcpy(dyn_CONFIGFILE, poptGetOptArg(pc));
+ break;
+ case 'u':
+ Ucrit_addUsername(poptGetOptArg(pc));
+ break;
+ default:
+ fprintf(stderr, "Usage: %s [-P] [-v] [-L] [-p] [-S] [-s configfile] [-u username] [-d debuglevel]\n", *argv);
+ return (-1);
+ }
+ }
+
+ if (!lp_load(dyn_CONFIGFILE,False,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
+ return (-1);
+ }
+
+ if (new_debuglevel != -1) {
+ DEBUGLEVEL = new_debuglevel;
+ }
+
+ if (verbose) {
+ d_printf("using configfile = %s\n", dyn_CONFIGFILE);
+ }
+
+ if (profile_only) {
+ return profile_dump();
+ }
+
+ tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
+ if (!tdb) {
+ d_printf("sessionid.tdb not initialised\n");
+ } else {
+ if (locks_only) goto locks;
+
+ d_printf("\nSamba version %s\n",VERSION);
+ d_printf("PID Username Group Machine \n");
+ d_printf("-------------------------------------------------------------------\n");
+
+ tdb_traverse(tdb, traverse_sessionid, NULL);
+ tdb_close(tdb);
+ }
+
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
+ if (!tdb) {
+ d_printf("connections.tdb not initialised\n");
+ } else {
+ if (verbose) {
+ d_printf("Opened status file %s\n", fname);
+ }
+
+ if (brief)
+ exit(0);
+
+ d_printf("\nService pid machine Connected at\n");
+ d_printf("-------------------------------------------------------\n");
+
+ tdb_traverse(tdb, traverse_fn1, NULL);
+ tdb_close(tdb);
+ }
+
+ locks:
+ if (processes_only) exit(0);
+
+ if (!shares_only) {
+ int ret;
+
+ if (!locking_init(1)) {
+ d_printf("Can't initialise locking module - exiting\n");
+ exit(1);
+ }
+
+ ret = share_mode_forall(print_share_mode);
+
+ if (ret == 0) {
+ d_printf("No locked files\n");
+ } else if (ret == -1) {
+ d_printf("locked file list truncated\n");
+ }
+
+ d_printf("\n");
+
+ if (show_brl) {
+ brl_forall(print_brl);
+ }
+
+ locking_end();
+ }
+
+ return (0);
+}
diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index e1f070a4b8..defde6cb2c 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -1,8 +1,7 @@
/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
Test validity of smb.conf
- Copyright (C) Karl Auer 1993, 1994
+ Copyright (C) Karl Auer 1993, 1994-1998
Extensively modified by Andrew Tridgell, 1995
@@ -34,80 +33,280 @@
#include "includes.h"
#include "smb.h"
-#include "params.h"
-#include "loadparm.h"
-/* these live in util.c */
-extern FILE *dbf;
-extern int DEBUGLEVEL;
+extern BOOL AllowDebugChange;
+
+/***********************************************
+ Here we do a set of 'hard coded' checks for bad
+ configuration settings.
+************************************************/
+
+static int do_global_checks(void)
+{
+ int ret = 0;
+ SMB_STRUCT_STAT st;
+
+ if (lp_security() >= SEC_DOMAIN && !lp_encrypted_passwords()) {
+ printf("ERROR: in 'security=domain' mode the 'encrypt passwords' parameter must also be set to 'true'.\n");
+ ret = 1;
+ }
+
+ if (lp_wins_support() && wins_srv_count()) {
+ printf("ERROR: both 'wins support = true' and 'wins server = <server>' \
+cannot be set in the smb.conf file. nmbd will abort with this setting.\n");
+ ret = 1;
+ }
+
+ if (!directory_exist(lp_lockdir(), &st)) {
+ printf("ERROR: lock directory %s does not exist\n",
+ lp_lockdir());
+ ret = 1;
+ } else if ((st.st_mode & 0777) != 0755) {
+ printf("WARNING: lock directory %s should have permissions 0755 for browsing to work\n",
+ lp_lockdir());
+ ret = 1;
+ }
+
+ /*
+ * Password server sanity checks.
+ */
+
+ if((lp_security() == SEC_SERVER || lp_security() >= SEC_DOMAIN) && !lp_passwordserver()) {
+ pstring sec_setting;
+ if(lp_security() == SEC_SERVER)
+ pstrcpy(sec_setting, "server");
+ else if(lp_security() == SEC_DOMAIN)
+ pstrcpy(sec_setting, "domain");
+
+ printf("ERROR: The setting 'security=%s' requires the 'password server' parameter be set \
+to a valid password server.\n", sec_setting );
+ ret = 1;
+ }
+
+
+ /*
+ * Check 'hosts equiv' and 'use rhosts' compatibility with 'hostname lookup' value.
+ */
+
+ if(*lp_hosts_equiv() && !lp_hostname_lookups()) {
+ printf("ERROR: The setting 'hosts equiv = %s' requires that 'hostname lookups = yes'.\n", lp_hosts_equiv());
+ ret = 1;
+ }
+
+ /*
+ * Password chat sanity checks.
+ */
+
+ if(lp_security() == SEC_USER && lp_unix_password_sync()) {
+
+ /*
+ * Check that we have a valid lp_passwd_program() if not using pam.
+ */
+
+#ifdef WITH_PAM
+ if (!lp_pam_password_change()) {
+#endif
+
+ if(lp_passwd_program() == NULL) {
+ printf("ERROR: the 'unix password sync' parameter is set and there is no valid 'passwd program' \
+parameter.\n" );
+ ret = 1;
+ } else {
+ pstring passwd_prog;
+ pstring truncated_prog;
+ char *p;
+
+ pstrcpy( passwd_prog, lp_passwd_program());
+ p = passwd_prog;
+ *truncated_prog = '\0';
+ next_token(&p, truncated_prog, NULL, sizeof(pstring));
+
+ if(access(truncated_prog, F_OK) == -1) {
+ printf("ERROR: the 'unix password sync' parameter is set and the 'passwd program' (%s) \
+cannot be executed (error was %s).\n", truncated_prog, strerror(errno) );
+ ret = 1;
+ }
+ }
+
+#ifdef WITH_PAM
+ }
+#endif
+
+ if(lp_passwd_chat() == NULL) {
+ printf("ERROR: the 'unix password sync' parameter is set and there is no valid 'passwd chat' \
+parameter.\n");
+ ret = 1;
+ }
+
+ /*
+ * Check that we have a valid script and that it hasn't
+ * been written to expect the old password.
+ */
+
+ if(lp_encrypted_passwords()) {
+ if(strstr( lp_passwd_chat(), "%o")!=NULL) {
+ printf("ERROR: the 'passwd chat' script [%s] expects to use the old plaintext password \
+via the %%o substitution. With encrypted passwords this is not possible.\n", lp_passwd_chat() );
+ ret = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void usage(char *pname)
+{
+ printf("Usage: %s [-sh] [-L servername] [configfilename] [hostname hostIP]\n", pname);
+ printf("\t-s Suppress prompt for enter\n");
+ printf("\t-h Print usage\n");
+ printf("\t-L servername Set %%L macro to servername\n");
+ printf("\t-t encoding Print parameters with encoding\n");
+ printf("\tconfigfilename Configuration file to test\n");
+ printf("\thostname hostIP. Hostname and Host IP address to test\n");
+ printf("\t against \"host allow\" and \"host deny\"\n");
+ printf("\n");
+}
+
int main(int argc, char *argv[])
{
+ extern char *optarg;
+ extern int optind;
+ extern fstring local_machine;
pstring configfile;
+ int opt;
int s;
+ BOOL silent_mode = False;
+ int ret = 0;
+ pstring term_code;
+
+ *term_code = 0;
setup_logging(argv[0],True);
- charset_initialise();
+ while ((opt = getopt(argc, argv,"shL:t:")) != EOF) {
+ switch (opt) {
+ case 's':
+ silent_mode = True;
+ break;
+ case 'L':
+ fstrcpy(local_machine,optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ case 't':
+ pstrcpy(term_code,optarg);
+ break;
+ default:
+ printf("Incorrect program usage\n");
+ usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+
+ argc += (1 - optind);
- if (argc < 2)
- strcpy(configfile,CONFIGFILE);
- else
- strcpy(configfile,argv[1]);
+ if ((argc == 1) || (argc == 3))
+ pstrcpy(configfile, dyn_CONFIGFILE);
+ else if ((argc == 2) || (argc == 4))
+ pstrcpy(configfile,argv[optind]);
- dbf = stdout;
+ dbf = x_stdout;
DEBUGLEVEL = 2;
+ AllowDebugChange = False;
printf("Load smb config files from %s\n",configfile);
- if (!lp_load(configfile,False))
- {
+ if (!lp_load(configfile,False,True,False)) {
printf("Error loading services.\n");
return(1);
- }
-
+ }
printf("Loaded services file OK.\n");
- for (s=0;s<1000;s++)
+ ret = do_global_checks();
+
+ for (s=0;s<1000;s++) {
if (VALID_SNUM(s))
if (strlen(lp_servicename(s)) > 8) {
- printf("WARNING: You have some share names that are longer than 8 chars\n");
- printf("These may give errors while browsing or may not be accessible\nto some older clients\n");
- break;
+ printf("WARNING: You have some share names that are longer than 8 chars\n");
+ printf("These may give errors while browsing or may not be accessible\nto some older clients\n");
+ break;
+ }
+ }
+
+ for (s=0;s<1000;s++) {
+ if (VALID_SNUM(s)) {
+ char **deny_list = lp_hostsdeny(s);
+ char **allow_list = lp_hostsallow(s);
+ int i;
+ if(deny_list) {
+ for (i=0; deny_list[i]; i++) {
+ char *hasstar = strchr_m(deny_list[i], '*');
+ char *hasquery = strchr_m(deny_list[i], '?');
+ if(hasstar || hasquery) {
+ printf("Invalid character %c in hosts deny list (%s) for service %s.\n",
+ hasstar ? *hasstar : *hasquery, deny_list[i], lp_servicename(s) );
+ }
+ }
}
- if (argc < 4)
- {
+ if(allow_list) {
+ for (i=0; allow_list[i]; i++) {
+ char *hasstar = strchr_m(allow_list[i], '*');
+ char *hasquery = strchr_m(allow_list[i], '?');
+ if(hasstar || hasquery) {
+ printf("Invalid character %c in hosts allow list (%s) for service %s.\n",
+ hasstar ? *hasstar : *hasquery, allow_list[i], lp_servicename(s) );
+ }
+ }
+ }
+
+ if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
+ printf("Invalid combination of parameters for service %s. \
+Level II oplocks can only be set if oplocks are also set.\n",
+ lp_servicename(s) );
+ }
+ }
+ }
+
+ if (argc < 3) {
+ if (!silent_mode) {
printf("Press enter to see a dump of your service definitions\n");
fflush(stdout);
getc(stdin);
- lp_dump();
}
+ lp_dump(stdout,True, lp_numservices());
+ }
- if (argc == 4)
- {
- struct from_host f;
- f.name = argv[2];
- f.addr = argv[3];
+ if (argc >= 3) {
+ char *cname;
+ char *caddr;
- /* this is totally ugly, a real `quick' hack */
- for (s=0;s<1000;s++)
- if (VALID_SNUM(s))
- {
- if (allow_access(lp_hostsdeny(s),lp_hostsallow(s),&f))
- {
- printf("Allow connection from %s (%s) to %s\n",
- f.name,f.addr,lp_servicename(s));
- }
- else
- {
- printf("Deny connection from %s (%s) to %s\n",
- f.name,f.addr,lp_servicename(s));
- }
- }
+ if (argc == 3) {
+ cname = argv[optind];
+ caddr = argv[optind+1];
+ } else {
+ cname = argv[optind+1];
+ caddr = argv[optind+2];
}
- return(0);
-}
-
+ /* this is totally ugly, a real `quick' hack */
+ for (s=0;s<1000;s++) {
+ if (VALID_SNUM(s)) {
+ if (allow_access(lp_hostsdeny(s),lp_hostsallow(s),cname,caddr)) {
+ printf("Allow connection from %s (%s) to %s\n",
+ cname,caddr,lp_servicename(s));
+ } else {
+ printf("Deny connection from %s (%s) to %s\n",
+ cname,caddr,lp_servicename(s));
+ }
+ }
+ }
+ }
+ return(ret);
+}
diff --git a/source3/utils/testprns.c b/source3/utils/testprns.c
index 89c615898d..66c8e9bfd6 100644
--- a/source3/utils/testprns.c
+++ b/source3/utils/testprns.c
@@ -1,8 +1,7 @@
/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
test printer setup
- Copyright (C) Karl Auer 1993, 1994
+ Copyright (C) Karl Auer 1993, 1994-1998
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
@@ -33,11 +32,6 @@
#include "includes.h"
#include "smb.h"
-#include "pcap.h"
-
-/* these live in util.c */
-extern FILE *dbf;
-extern int DEBUGLEVEL;
int main(int argc, char *argv[])
{
@@ -45,17 +39,14 @@ int main(int argc, char *argv[])
setup_logging(argv[0],True);
- charset_initialise();
-
if (argc < 2 || argc > 3)
printf("Usage: testprns printername [printcapfile]\n");
else
{
- dbf = fopen("test.log", "w");
- if (dbf == NULL)
+ dbf = x_fopen("test.log", O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (dbf == NULL) {
printf("Unable to open logfile.\n");
- else
- {
+ } else {
DEBUGLEVEL = 3;
pszTemp = (argc < 3) ? PRINTCAP_NAME : argv[2];
printf("Looking for printer %s in printcap file %s\n",
@@ -64,9 +55,8 @@ int main(int argc, char *argv[])
printf("Printer name %s is not valid.\n", argv[1]);
else
printf("Printer name %s is valid.\n", argv[1]);
- fclose(dbf);
+ x_fclose(dbf);
}
}
return (0);
}
-