1#!/usr/bin/env python 2""" 3ntlogon.py written by Timothy (rhacer) Grant 4 5Copyright 1999 - 2002 by Timothy Grant 6 7is distributed under the terms of the GNU Public License. 8 9The format for the configuration file is as follows: 10 11While there is some room for confusion, we attempt to process things in 12order of specificity: Global first, Group second, User third, OS Type 13forth. This order can be debated forever, but it seems to make the most 14sense. 15 16# Everything in the Global section applies to all users logging on to the 17# network 18[Global] 19@ECHO "Welcome to our network!!!" 20NET TIME \\\\servername /SET /YES 21NET USE F: \\\\servername\\globalshare /YES 22 23# Map the private user area in the global section so we don't have to 24# create individual user entries for each user! 25NET USE U: \\\\servername\\%U /YES 26 27# Group entries, User entries and OS entries each start with the 28# keyword followed by a dash followed by--appropriately enough the Group 29# name, the User name, or the OS name. 30[Group-admin] 31@ECHO "Welcome administrators!" 32NET USE G: \\\\servername\\adminshare1 /YES 33NET USE I: \\\\servername\\adminshare2 /YES 34 35[Group-peons] 36@ECHO "Be grateful we let you use computers!" 37NET USE G: \\\\servername\\peonshare1 /YES 38 39[Group-hackers] 40@ECHO "What can I do for you today great one?" 41NET USE G: \\\\servername\\hackershare1 /YES 42NET USE I: \\\\servername\\adminshare2 /YES 43 44[User-fred] 45@ECHO "Hello there Fred!" 46NET USE F: \\\\servername\\fredsspecialshare /YES 47 48[OS-WfWg] 49@ECHO "Time to upgrade it?" 50 51# End configuration file 52 53usage: ntlogon [-g | --group=groupname] 54 [-u | --user=username] 55 [-o | --os=osname] 56 [-m | --machine=netbiosname] 57 [-f | --templatefile=filename] 58 [-d | --dir=netlogon directory] 59 [-v | --version] 60 [-h | --help] 61 [--pause] 62 [--debug] 63""" 64# 65#" This quote mark is an artifact of the inability of my editor to 66# correctly colour code anything after the triple-quoted docstring. 67# if your editor does not have this flaw, feel free to remove it. 68 69 70import sys 71import getopt 72import re 73import string 74import os 75 76version = "ntlogon.py v0.8" 77 78def buildScript(buf, sections, group, user, ostype, machine, debug, pause): 79 """ 80 buildScript() Takes the contents of the template file and builds 81 a DOS batch file to be executed as an NT logon script. It does this 82 by determining which sections of the configuration file should be included 83 and creating a list object that contains each line contained in each 84 included section. The list object is then returned to the calling 85 routine. 86 87 All comments (#) are removed. A REM is inserted to show 88 which section of the configuration file each line comes from. 89 We leave blanklines as they are sometimes useful for debugging 90 91 We also replace all of the Samba macros (e.g., %U, %G, %a, %m) with their 92 expanded versions which have been passed to us by smbd 93 """ 94 hdrstring = '' 95 script = [] 96 97 # 98 # These are the Samba macros that we currently know about. 99 # any user defined macros will also be added to this dictionary. 100 # We do not store the % sign as part of the macro name. 101 # The replace routine will prepend the % sign to all possible 102 # replacements. 103 # 104 macros = { 105 'U': user, 106 'G': group, 107 'a': ostype, 108 'm': machine 109 } 110 111 # 112 # Process each section defined in the list sections 113 # 114 for s in sections: 115 # print 'searching for: ' + s 116 117 idx = 0 118 119 while idx < len(buf): 120 ln = buf[idx] 121 122 # 123 # We need to set up a regex for each possible section we 124 # know about. This is slightly complicated due to the fact 125 # that section headers contain user defined text. 126 # 127 if s == 'Global': 128 hdrstring = '\[ *' + s + ' *\]' 129 elif s == 'Group': 130 hdrstring = '\[ *' + s + ' *- *' + group + ' *\]' 131 elif s == 'User': 132 hdrstring = '\[ *' + s + ' *- *' + user + ' *\]' 133 elif s == 'OS': 134 hdrstring = '\[ *' + s + ' *- *' + ostype + ' *\]' 135 elif s == 'Machine': 136 hdrstring = '\[ *' + s + ' *- *' + machine + ' *\]' 137 138 # 139 # See if we have found a section header 140 # 141 if re.search(r'(?i)' + hdrstring, ln): 142 idx = idx + 1 # increment the counter to move to the next 143 # line. 144 145 x = re.match(r'([^#\r\n]*)', ln) # Determine the section 146 # name and strip out CR/LF 147 # and comment information 148 149 if debug: 150 print 'rem ' + x.group(1) + ' commands' 151 else: 152 # create the rem at the beginning of each section of the 153 # logon script. 154 script.append('rem ' + x.group(1) + ' commands') 155 156 # 157 # process each line until we have found another section 158 # header 159 # 160 while not re.search(r'.*\[.*\].*', buf[idx]): 161 162 # 163 # strip comments and line endings 164 # 165 x = re.match(r'([^#\r\n]*)', buf[idx]) 166 167 if string.strip(x.group(1)) != '' : 168 # if there is still content after stripping comments and 169 # line endings then this is a line to process 170 171 line = x.group(1) 172 173 # 174 # Check to see if this is a macro definition line 175 # 176 vardef = re.match(r'(.*)=(.*)', line) 177 178 if vardef: 179 varname = string.strip(vardef.group(1)) # Strip leading and 180 varsub = string.strip(vardef.group(2)) # and trailing spaces 181 182 if varname == '': 183 print "Error: No substition name specified line: %d" % idx 184 sys.exit(1) 185 186 if varsub == '': 187 print "Error: No substitution text provided line: %d" % idx 188 sys.exit(1) 189 190 if macros.has_key(varname): 191 print "Warning: macro %s redefined line: %d" % (varname, idx) 192 193 macros[varname] = varsub 194 idx = idx + 1 195 continue 196 197 # 198 # Replace all the macros that we currently 199 # know about. 200 # 201 # Iterate over the dictionary that contains all known 202 # macro substitutions. 203 # 204 # We test for a macro name by prepending % to each dictionary 205 # key. 206 # 207 for varname in macros.keys(): 208 line = re.sub(r'%' + varname + r'(\W)', 209 macros[varname] + r'\1', line) 210 211 if debug: 212 print line 213 if pause: 214 print 'pause' 215 else: 216 script.append(line) 217 218 idx = idx + 1 219 220 if idx == len(buf): 221 break # if we have reached the end of the file 222 # stop processing. 223 224 idx = idx + 1 # increment the line counter 225 226 if debug: 227 print '' 228 else: 229 script.append('') 230 231 return script 232 233# End buildScript() 234 235def run(): 236 """ 237 run() everything starts here. The main routine reads the command line 238 arguments, opens and reads the configuration file. 239 """ 240 configfile = '/etc/ntlogon.conf' # Default configuration file 241 group = '' # Default group 242 user = '' # Default user 243 ostype = '' # Default os 244 machine = '' # Default machine type 245 outfile = 'logon.bat' # Default batch file name 246 # this file name WILL take on the form 247 # username.bat if a username is specified 248 debug = 0 # Default debugging mode 249 pause = 0 # Default pause mode 250 outdir = '/usr/local/samba/netlogon/' # Default netlogon directory 251 252 sections = ['Global', 'Machine', 'OS', 'Group', 'User'] # Currently supported 253 # configuration file 254 # sections 255 256 options, args = getopt.getopt(sys.argv[1:], 'd:f:g:ho:u:m:v', 257 ['templatefile=', 258 'group=', 259 'help', 260 'os=', 261 'user=', 262 'machine=', 263 'dir=', 264 'version', 265 'pause', 266 'debug']) 267 268 # 269 # Process the command line arguments 270 # 271 for i in options: 272 # template file to process 273 if (i[0] == '-f') or (i[0] == '--templatefile'): 274 configfile = i[1] 275 # print 'configfile = ' + configfile 276 277 # define the group to be used 278 elif (i[0] == '-g') or (i[0] == '--group'): 279 group = i[1] 280 # print 'group = ' + group 281 282 # define the os type 283 elif (i[0] == '-o') or (i[0] == '--os'): 284 ostype = i[1] 285 # print 'os = ' + os 286 287 # define the user 288 elif (i[0] == '-u') or (i[0] == '--user'): 289 user = i[1] 290 outfile = user + '.bat' # Setup the output file name 291 # print 'user = ' + user 292 293 # define the machine 294 elif (i[0] == '-m') or (i[0] == '--machine'): 295 machine = i[1] 296 297 # define the netlogon directory 298 elif (i[0] == '-d') or (i[0] == '--dir'): 299 outdir = i[1] 300 # print 'outdir = ' + outdir 301 302 # if we are asked to turn on debug info, do so. 303 elif (i[0] == '--debug'): 304 debug = 1 305 # print 'debug = ' + debug 306 307 # if we are asked to turn on the automatic pause functionality, do so 308 elif (i[0] == '--pause'): 309 pause = 1 310 # print 'pause = ' + pause 311 312 # if we are asked for the version number, print it. 313 elif (i[0] == '-v') or (i[0] == '--version'): 314 print version 315 sys.exit(0) 316 317 # if we are asked for help print the docstring. 318 elif (i[0] == '-h') or (i[0] == '--help'): 319 print __doc__ 320 sys.exit(0) 321 322 # 323 # open the configuration file 324 # 325 try: 326 iFile = open(configfile, 'r') 327 except IOError: 328 print 'Unable to open configuration file: ' + configfile 329 sys.exit(1) 330 331 332 # 333 # open the output file 334 # 335 if not debug: 336 try: 337 oFile = open(outdir + outfile, 'w') 338 except IOError: 339 print 'Unable to open logon script file: ' + outdir + outfile 340 sys.exit(1) 341 342 buf = iFile.readlines() # read in the entire configuration file 343 344 # 345 # call the script building routine 346 # 347 script = buildScript(buf, sections, group, user, ostype, machine, debug, pause) 348 349 # 350 # write out the script file 351 # 352 if not debug: 353 for ln in script: 354 oFile.write(ln + '\r\n') 355 if pause: 356 if string.strip(ln) != '': # Because whitespace 357 oFile.write('pause' + '\r\n') # is a useful tool, we 358 # don't put pauses after 359 # an empty line. 360 361 362# End run() 363 364# 365# immediate-mode commands, for drag-and-drop or execfile() execution 366# 367if __name__ == '__main__': 368 run() 369else: 370 print "Module ntlogon.py imported." 371 print "To run, type: ntlogon.run()" 372 print "To reload after changes to the source, type: reload(ntlogon)" 373 374# 375# End NTLogon.py 376# 377