#!/usr/bin/env python # -*- coding: UTF-8 -*- ########################################################################## # Tcos writen by MarioDebian # # tcos-gdm-autologin # # Copyright (c) 2006 Mario Izquierdo # # 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, 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., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. ########################################################################### """ Usage: * from GDM this app is called to retrieve username based on hostname * Exec standalone, configure GDM /etc/gdm/gdm.conf file with ThinClient values """ import os, sys import getopt import popen2 from socket import gethostbyaddr as gethostname GDM_CONF_FILE="/etc/gdm/gdm.conf" HOME_TEMPLATE="/root/skel.tar.gz" USER_GROUPS=["fuse"] debug=False configure=False add=False delete_home=True noaction=False # this is the values needed to connect to GDM from thin clients TCOS_GDM={ "daemon":[ {"TimedLoginEnable":"true"}, {"TimedLogin":"/usr/sbin/tcos-gdm-autologin|"}, {"TimedLoginDelay":"10"} ], "security":[ {"AllowRemoteAutoLogin":"true"}, {"DisallowTCP":"false"} ], "xdmcp":[ {"Enable":"true"} ] } def print_debug(txt): if debug: sys.stderr.write("%s::%s\n" %("tcos-gdm-autologin", txt)) #print "%s::%s" %("tcos-gdm-autologin", txt) def usage(): print "tcos-gdm-autologin help:" print "" print " [no options] (write username to login, used from GDM)" print " -d [--debug] (write debug data to stdout)" print " -h [--help] (this help)" print " --configure (configure gdm with ThinClient values)" print " --skel=/foo/bar/file.tar.gz (skel template, default %s)" %(HOME_TEMPLATE) print " --add (add users and hostnames to system files)" print " --nodelete (NOT delete HOME and uncompress HOME_TEMPLATE)" print " --noaction (NOT perform any action, enable debug)" try: opts, args = getopt.getopt(sys.argv[1:], ":hd", ["help", "debug", "configure", "skel=", "add", "nodelete", "noaction"]) except getopt.error, msg: print msg print "for command line options use tcos-gdm-autologin --help" sys.exit(2) # process options for o, a in opts: if o in ("-d", "--debug"): #print "DEBUG ACTIVE" debug = True if o == "--configure": configure=True if o == "--add": add=True if o == "--nodelete": delete_home=False if o == "--noaction": noaction=True debug=True if o == "--skel": HOME_TEMPLATE=a if o in ("-h", "--help"): usage() sys.exit(0) ######################################################## # # Extends python-configobj class to use '=' instead of ' = ' # ######################################################## from configobj import ConfigObj class MyConfigObj (ConfigObj): def _write_line(self, indent_string, entry, this_entry, comment): """Write an individual line, for the write method""" # NOTE: the calls to self._quote here handles non-StringType values. if not self.unrepr: val = self._decode_element(self._quote(this_entry)) else: val = repr(this_entry) return '%s%s%s%s%s' % ( indent_string, self._decode_element(self._quote(entry, multiline=False)), self._a_to_u('='), val, self._decode_element(comment)) ######## some functions ############# def execmd(cmd): if not noaction: print_debug(cmd) try: if not noaction: os.system(cmd) else: print_debug("NOACTION: execmd() cmd=%s" %(cmd) ) except: print("Error while exec: \"%s\"" %(cmd) ) def is_ip(host): try: if len( host.split('.') ) == 4: print_debug("is_ip: host=%s seems to be an IP address" %(host) ) return True return False except: return False def show_login(): username=None host=None home=None display=None host, display = os.environ["DISPLAY"].split(':') if host == "": print_debug ( "localdisplay no have username" ) sys.exit(1) if is_ip(host): try: host=gethostname(host)[0] print_debug("show_login() convert IP to hostname host=%s" %(host)) except: print_debug("show_login() error converting IP to hostname") # read home for hostname:user f=open("/etc/passwd", "r") data=f.readlines() f.close() newdata=[] for line in data: newdata.append(line.replace('\n', '')) data=newdata for line in data: if host == line.split(':')[0]: (username, home) = ( line.split(':')[0], line.split(':')[5] ) if not username or not os.path.isdir(home): print "no_username_configured_for_host_%s" %(host) print_debug("ERROR, username=%s or home=%s not set or not found in /etc/passwd." %(username, home)) sys.exit(1) # kill all user processes execmd("pkill -9 -u %s" %(username)) if delete_home: restore_home(home, username) else: print_debug("Not restoring home...") print username def read_exe_output(cmd): output=[] if noaction: print_debug("NOACTION: read_exe_output() cmd=%s" %(cmd) ) return output (stdout, stdin) = popen2.popen2(cmd) stdin.close() for line in stdout: if line != '\n': line=line.replace('\n', '') output.append(line) return output def restore_home(home, username): if noaction: print_debug("NOACTION: restore_home() home=%s username=%s" %(home,username) ) return if not os.path.isfile(HOME_TEMPLATE): print_debug ( "skel don't exists: %s" %(HOME_TEMPLATE) ) return # umount all fuse devices if int(read_exe_output("grep -c \"%s\" /proc/mounts" %(home) )[0] ) > 0: print_debug("user %s have fuse mounted devices" %(username) ) for mount_dev in read_exe_output("grep \"%s\" /proc/mounts | awk '{print $2}'" %(home) ): print_debug("umounting %s" %(mount_dev) ) execmd("fusermount -u %s" %(mount_dev) ) execmd("rm -rf %s 2>/dev/null" %(home) ) try: os.mkdir(home) except: pass execmd("tar -zxf %s -C %s 2>/dev/null" %(HOME_TEMPLATE, home) ) execmd("chown -R %s:%s %s 2>/dev/null" %(username, username, home) ) def SetVar(section, key, value): GDMCONF=GDM_CONF_FILE # try to edit correct file (Ubuntu use -custom file) if os.path.isfile(GDM_CONF_FILE + "-custom"): GDMCONF=GDM_CONF_FILE+"-custom" if noaction: print_debug("NOACTION: SetVar() gdm.conf=%s section=%s key=%s value=%s" %(GDMCONF, section,key,value) ) return config=MyConfigObj( os.path.realpath(GDMCONF) ) print_debug("setting section=[%s] key=%s value=%s" %(section, key, value) ) config[section][key] = value try: config.write() except: print "Error, can't write in %s" %(GDMCONF) def SetAutologin(): for section in TCOS_GDM: for var in TCOS_GDM[section]: for key in var: value=var[key] SetVar(section, key, value) print ("gdm config file edited") return def AddUserAndHost(): hosts=[] ips=[] prefix=raw_input("Please input the common prefix of hosts/users (example host): ") ipbase=raw_input("Need network IP Address of thin clients (example 192.168.0): ") number=int(raw_input("Number of host/users to generate (number): ")) fromip=int( raw_input("Start generating from (default 1): ") ) if fromip == "" : fromip = 1 for i in range(fromip,number+fromip): hosts.append("%s%s" %(prefix, i)) ips.append("%s.%s" %(ipbase, i)) print "" print "I will generate users and hostnames from \"%s\" to \"%s\"" %(hosts[0], hosts[-1]) print "with ip adresses from %s to %s" %(ips[0], ips[-1]) if os.path.isfile(HOME_TEMPLATE): print "and uncompress \"%s\" as HOME_TEMPLATE" %(HOME_TEMPLATE) else: print "and **** I'M NOT USING ANY HOME TEMPLATE ****" print "Cancel now and create %s using a template user" %(HOME_TEMPLATE) print "" resp=raw_input("Are you sure to continue? [y/n] ") if resp != "y" and resp != "Y": print "cancelled." return for i in range(fromip,number+fromip): AddUser( "%s%s" %(prefix, i) ) AddHost( "%s%s" %(prefix, i) , "%s.%s" %(ipbase, i) ) print "done." def AddUser(username): print ( "Adding user: %s" %(username) ) execmd("useradd -m %s -p%s -s /bin/bash -d /home/%s" %(username, username, username)) execmd("echo %s:%s | chpasswd" %(username, username)) execmd("tar -zxf %s -C /home/%s 2>/dev/null" %(HOME_TEMPLATE, username) ) execmd("chown %s:%s /home/%s " %(username, username, username) ) for group in USER_GROUPS: execmd("adduser %s %s" %(username, group)) def AddHost(hostname, ip): # check if exists f=open("/etc/hosts", "r") data=f.readlines() f.close() for line in data: line=line.replace('\n','') if ip + " " in line or ip + '\t' in line: print ( "IP %s is in /etc/hosts" %(ip) ) return try: print ("Adding %s %s" %(ip, hostname) ) if noaction: print_debug("NOACTION: AddHost() hostname=%s, ip=%s" %(hostname,ip) ) else: f=open("/etc/hosts", "a") f.write("%s\t%s\n" %(ip, hostname) ) f.close() except: print "Error editting /etc/hosts, are you root?" pass try: if configure: SetAutologin() elif add: AddUserAndHost() else: show_login() except KeyboardInterrupt: # Por si se pulsa Ctrl+C print "\nCtrl+C event, quit now..." sys.exit(1) # end of file