Merge commit 'ceod'
This commit is contained in:
commit
873f7ac9a6
|
@ -1,4 +1,3 @@
|
|||
/build-stamp
|
||||
/build
|
||||
*.pyc
|
||||
*.cf
|
|
@ -23,11 +23,9 @@ cfg = {}
|
|||
def configure():
|
||||
"""Load Members Configuration"""
|
||||
|
||||
string_fields = [ 'username_regex', 'shells_file', 'server_url',
|
||||
'users_base', 'groups_base', 'sasl_mech', 'sasl_realm',
|
||||
'admin_bind_keytab', 'admin_bind_userid', 'realm',
|
||||
'admin_principal', 'admin_keytab', 'expired_account_email',
|
||||
'mathsoc_regex', 'mathsoc_dont_count' ]
|
||||
string_fields = [ 'username_regex', 'shells_file', 'ldap_server_url',
|
||||
'ldap_users_base', 'ldap_groups_base', 'ldap_sasl_mech', 'ldap_sasl_realm',
|
||||
'expire_hook', 'mathsoc_regex', 'mathsoc_dont_count' ]
|
||||
numeric_fields = [ 'min_password_length' ]
|
||||
|
||||
# read configuration file
|
||||
|
@ -93,8 +91,8 @@ def connect(auth_callback):
|
|||
tries = 0
|
||||
while ld is None:
|
||||
try:
|
||||
ld = ldapi.connect_sasl(cfg['server_url'], cfg['sasl_mech'],
|
||||
cfg['sasl_realm'], password)
|
||||
ld = ldapi.connect_sasl(cfg['ldap_server_url'], cfg['ldap_sasl_mech'],
|
||||
cfg['ldap_sasl_realm'], password)
|
||||
except ldap.LOCAL_ERROR, e:
|
||||
tries += 1
|
||||
if tries > 3:
|
||||
|
@ -178,10 +176,10 @@ def get(userid):
|
|||
}
|
||||
"""
|
||||
|
||||
return ldapi.lookup(ld, 'uid', userid, cfg['users_base'])
|
||||
return ldapi.lookup(ld, 'uid', userid, cfg['ldap_users_base'])
|
||||
|
||||
def uid2dn(uid):
|
||||
return 'uid=%s,%s' % (ldapi.escape(uid), cfg['users_base'])
|
||||
return 'uid=%s,%s' % (ldapi.escape(uid), cfg['ldap_users_base'])
|
||||
|
||||
|
||||
def list_term(term):
|
||||
|
@ -200,7 +198,7 @@ def list_term(term):
|
|||
}
|
||||
"""
|
||||
|
||||
members = ldapi.search(ld, cfg['users_base'],
|
||||
members = ldapi.search(ld, cfg['ldap_users_base'],
|
||||
'(&(objectClass=member)(term=%s))', [ term ])
|
||||
return dict([(member[0], member[1]) for member in members])
|
||||
|
||||
|
@ -220,7 +218,7 @@ def list_name(name):
|
|||
]
|
||||
"""
|
||||
|
||||
members = ldapi.search(ld, cfg['users_base'],
|
||||
members = ldapi.search(ld, cfg['ldap_users_base'],
|
||||
'(&(objectClass=member)(cn~=%s))', [ name ])
|
||||
return dict([(member[0], member[1]) for member in members])
|
||||
|
||||
|
@ -262,7 +260,7 @@ def list_all():
|
|||
]
|
||||
"""
|
||||
|
||||
members = ldapi.search(ld, cfg['users_base'], '(objectClass=member)')
|
||||
members = ldapi.search(ld, cfg['ldap_users_base'], '(objectClass=member)')
|
||||
return dict([(member[0], member[1]) for member in members])
|
||||
|
||||
|
||||
|
@ -278,7 +276,7 @@ def list_positions():
|
|||
]
|
||||
"""
|
||||
|
||||
members = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE, '(position=*)')
|
||||
members = ld.search_s(cfg['ldap_users_base'], ldap.SCOPE_SUBTREE, '(position=*)')
|
||||
positions = {}
|
||||
for (_, member) in members:
|
||||
for position in member['position']:
|
||||
|
@ -299,7 +297,7 @@ def set_position(position, members):
|
|||
Example: set_position('president', ['dtbartle'])
|
||||
"""
|
||||
|
||||
res = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE,
|
||||
res = ld.search_s(cfg['ldap_users_base'], ldap.SCOPE_SUBTREE,
|
||||
'(&(objectClass=member)(position=%s))' % ldapi.escape(position))
|
||||
old = set([ member['uid'][0] for (_, member) in res ])
|
||||
new = set(members)
|
||||
|
@ -312,7 +310,7 @@ def set_position(position, members):
|
|||
|
||||
for action in ['del', 'add']:
|
||||
for userid in mods[action]:
|
||||
dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||
dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base'])
|
||||
entry1 = {'position' : [position]}
|
||||
entry2 = {} #{'position' : []}
|
||||
entry = ()
|
||||
|
@ -325,8 +323,8 @@ def set_position(position, members):
|
|||
|
||||
|
||||
def change_group_member(action, group, userid):
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||
group_dn = 'cn=%s,%s' % (ldapi.escape(group), cfg['groups_base'])
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base'])
|
||||
group_dn = 'cn=%s,%s' % (ldapi.escape(group), cfg['ldap_groups_base'])
|
||||
entry1 = {'uniqueMember' : []}
|
||||
entry2 = {'uniqueMember' : [user_dn]}
|
||||
entry = []
|
||||
|
@ -344,7 +342,7 @@ def change_group_member(action, group, userid):
|
|||
### Shells ###
|
||||
|
||||
def get_shell(userid):
|
||||
member = ldapi.lookup(ld, 'uid', userid, cfg['users_base'])
|
||||
member = ldapi.lookup(ld, 'uid', userid, cfg['ldap_users_base'])
|
||||
if not member:
|
||||
raise NoSuchMember(userid)
|
||||
if 'loginShell' not in member:
|
||||
|
@ -363,7 +361,7 @@ def get_shells():
|
|||
def set_shell(userid, shell):
|
||||
if not shell in get_shells():
|
||||
raise InvalidArgument("shell", shell, "is not in %s" % cfg['shells_file'])
|
||||
ldapi.modify(ld, 'uid', userid, cfg['users_base'], [ (ldap.MOD_REPLACE, 'loginShell', [ shell ]) ])
|
||||
ldapi.modify(ld, 'uid', userid, cfg['ldap_users_base'], [ (ldap.MOD_REPLACE, 'loginShell', [ shell ]) ])
|
||||
|
||||
|
||||
|
||||
|
@ -420,7 +418,7 @@ def register(userid, term_list):
|
|||
Example: register(3349, ["w2007", "s2007"])
|
||||
"""
|
||||
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base'])
|
||||
|
||||
if type(term_list) in (str, unicode):
|
||||
term_list = [ term_list ]
|
||||
|
@ -452,7 +450,7 @@ def register(userid, term_list):
|
|||
def register_nonmember(userid, term_list):
|
||||
"""Registers a non-member for one or more terms."""
|
||||
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base'])
|
||||
|
||||
if type(term_list) in (str, unicode):
|
||||
term_list = [ term_list ]
|
||||
|
@ -511,7 +509,7 @@ def group_members(group):
|
|||
Returns a list of group members
|
||||
"""
|
||||
|
||||
group = ldapi.lookup(ld, 'cn', group, cfg['groups_base'])
|
||||
group = ldapi.lookup(ld, 'cn', group, cfg['ldap_groups_base'])
|
||||
|
||||
if group and 'uniqueMember' in group:
|
||||
r = re.compile('^uid=([^,]*)')
|
||||
|
@ -519,11 +517,11 @@ def group_members(group):
|
|||
return []
|
||||
|
||||
def expired_accounts():
|
||||
members = ldapi.search(ld, cfg['users_base'],
|
||||
members = ldapi.search(ld, cfg['ldap_users_base'],
|
||||
'(&(objectClass=member)(!(|(term=%s)(nonMemberTerm=%s))))' %
|
||||
(terms.current(), terms.current()))
|
||||
return dict([(member[0], member[1]) for member in members])
|
||||
|
||||
def send_account_expired_email(name, email):
|
||||
args = [ cfg['expired_account_email'], name, email ]
|
||||
os.spawnv(os.P_WAIT, cfg['expired_account_email'], args)
|
||||
args = [ cfg['expire_hook'], name, email ]
|
||||
os.spawnv(os.P_WAIT, cfg['expire_hook'], args)
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
/ceo.substvars
|
||||
/ceo
|
||||
/ceo-common
|
||||
/ceo-clients
|
||||
/ceo-daemon
|
||||
/ceo-gui
|
||||
/files
|
||||
/*.debhelper
|
||||
/*.debhelper.log
|
||||
/*.substvars
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
docs/addclub.1
|
||||
docs/addmember.1
|
|
@ -0,0 +1 @@
|
|||
etc/csc
|
|
@ -0,0 +1 @@
|
|||
etc/accounts.cf etc/library.cf etc/ops etc/spam etc/csc
|
|
@ -1,3 +1 @@
|
|||
usr/bin
|
||||
etc/csc
|
||||
etc/ldap/schema
|
|
@ -0,0 +1 @@
|
|||
etc/csc.schema etc/ldap/schema
|
|
@ -0,0 +1 @@
|
|||
docs/ceo.1
|
|
@ -1,3 +1,8 @@
|
|||
ceo (0.4.24) stable testing; urgency=low
|
||||
|
||||
* Bump standards version.
|
||||
|
||||
-- Michael Spang <mspang@uwaterloo.ca> Wed, 29 Jul 2009 07:31:24 -0400
|
||||
ceo (0.4.23) stable testing; urgency=low
|
||||
|
||||
* CEO library now only finds books that are signed out as being overdue.
|
||||
|
|
|
@ -2,13 +2,32 @@ Source: ceo
|
|||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Systems Committee <syscom@csclub.uwaterloo.ca>
|
||||
Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev
|
||||
Standards-Version: 3.8.0
|
||||
Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev, libacl1-dev
|
||||
Standards-Version: 3.8.2
|
||||
|
||||
Package: ceo
|
||||
Architecture: any
|
||||
Depends: python-sqlobject, python-psycopg, python-ldap, python-urwid, ${python:Depends}, ${shlibs:Depends}
|
||||
Description: Computer Science Club Administrative Utilities
|
||||
Package: ceo-common
|
||||
Architecture: all
|
||||
Description: Computer Science Club Common Files
|
||||
This package contains the CSC Electronic Office
|
||||
and other Computer Science Club administrative
|
||||
programs.
|
||||
common files.
|
||||
|
||||
Package: ceo-gui
|
||||
Architecture: all
|
||||
Depends: ceo-clients, python-ldap, python-urwid, python-sqlobject, python-psycopg, ${python:Depends}, ${shlibs:Depends}
|
||||
Description: Computer Science Club Administrative GUI
|
||||
This package contains the CSC Electronic Office
|
||||
graphical user interface.
|
||||
|
||||
Package: ceo-clients
|
||||
Architecture: any
|
||||
Depends: ceo-common, ${shlibs:Depends}
|
||||
Description: Computer Science Club Administrative Clients
|
||||
This package contains the CSC Electronic Office
|
||||
client programs.
|
||||
|
||||
Package: ceo-daemon
|
||||
Architecture: any
|
||||
Depends: ceo-common, ${shlibs:Depends}
|
||||
Description: Computer Science Club Administrative Daemon
|
||||
This package contains the CSC Electronic Office
|
||||
daemon.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
docs/*
|
|
@ -1,2 +0,0 @@
|
|||
etc/accounts.cf.example etc/kerberos.cf.example etc/ldap.cf.example etc/csc
|
||||
etc/csc.schema etc/ldap/schema
|
|
@ -1 +0,0 @@
|
|||
docs/*.[0-9]
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
CFLAGS := -g -O2 -fstack-protector-all -fPIE
|
||||
LDFLAGS := -pie
|
||||
LDFLAGS := -pie -Wl,--as-needed
|
||||
|
||||
build:
|
||||
python setup.py -q build
|
||||
|
@ -18,13 +18,14 @@ install: build
|
|||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdirs
|
||||
python setup.py -q install --no-compile -O0 --root=debian/ceo
|
||||
$(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo PREFIX=/usr install
|
||||
|
||||
python setup.py -q install --no-compile -O0 --root=debian/ceo-gui
|
||||
$(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo-clients PREFIX=/usr install_clients
|
||||
$(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo-daemon PREFIX=/usr install_daemon
|
||||
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_installexamples
|
||||
dh_install
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# /etc/csc/accounts.cf: CSC Accounts Configuration
|
||||
|
||||
### Member Account Options ###
|
||||
|
||||
member_min_id = 20001
|
||||
member_max_id = 29999
|
||||
member_shell = "/bin/bash"
|
||||
member_home = "/users"
|
||||
member_home_acl = "u::rwx,g::rx,o::rx"
|
||||
member_home_skel = "/users/skel"
|
||||
|
||||
### Club Account Options ###
|
||||
|
||||
club_min_id = 30001
|
||||
club_max_id = 39999
|
||||
club_shell = "/bin/bash"
|
||||
club_home = "/users"
|
||||
club_home_acl = "A+group:%s:rwpRAxaWdDcCs:fd:allow"
|
||||
club_home_skel = "/users/skel"
|
||||
|
||||
### Administrative Account Options ###
|
||||
|
||||
admin_min_id = 10001
|
||||
admin_max_id = 19999
|
||||
|
||||
### LDAP Options ###
|
||||
|
||||
ldap_server_url = "ldaps://ldap-master.csclub.uwaterloo.ca"
|
||||
ldap_users_base = "ou=People,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
ldap_groups_base = "ou=Group,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
ldap_sudo_base = "ou=SUDOers,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
ldap_sasl_mech = "GSSAPI"
|
||||
ldap_sasl_realm = "CSCLUB.UWATERLOO.CA"
|
||||
ldap_admin_principal = "ceod/admin@CSCLUB.UWATERLOO.CA"
|
||||
|
||||
### Kerberos Options ###
|
||||
|
||||
krb5_realm = "CSCLUB.UWATERLOO.CA"
|
||||
krb5_admin_principal = "ceod/admin@CSCLUB.UWATERLOO.CA"
|
||||
|
||||
### Spam ###
|
||||
|
||||
notify_hook = "/etc/csc/spam/new-member"
|
||||
expire_hook = "/etc/csc/spam/expired-account"
|
||||
|
||||
### Miscellaneous ###
|
||||
|
||||
username_regex = "^[a-z][-a-z0-9]*$"
|
||||
min_password_length = 4
|
||||
shells_file = "/etc/shells"
|
||||
mathsoc_regex = ".*(mat/|vpa/se|computer science|math).*"
|
||||
mathsoc_dont_count = "cpdohert dlgawley dtbartle mbiggs saforres tmyklebu mgregson rridge dbelange"
|
|
@ -1,46 +0,0 @@
|
|||
# /etc/csc/accounts.cf: CSC Accounts Configuration
|
||||
|
||||
include /etc/csc/ldap.cf
|
||||
include /etc/csc/kerberos.cf
|
||||
|
||||
### Member Account Options ###
|
||||
|
||||
member_min_id = 20001
|
||||
member_max_id = 29999
|
||||
member_shell = "/bin/bash"
|
||||
member_home = "/users"
|
||||
#member_home_acl = "u::rwx,g::rx,o::rx"
|
||||
#member_home_dacl =
|
||||
member_home_acl =
|
||||
|
||||
### Club Account Options ###
|
||||
|
||||
club_min_id = 30001
|
||||
club_max_id = 39999
|
||||
club_shell = "/bin/bash"
|
||||
club_home = "/users"
|
||||
club_home_acl = "A+group:%s:rwpRAxaWdDcCs:fd:allow"
|
||||
|
||||
### Administrative Account Options
|
||||
|
||||
admin_min_id = 10001
|
||||
admin_max_id = 19999
|
||||
admin_shell = "/bin/bash"
|
||||
admin_home = "/users"
|
||||
|
||||
### Home Directory Options ###
|
||||
|
||||
skeleton_dir = "/users/skel"
|
||||
homedir_mode = "0755"
|
||||
refquota = "4G"
|
||||
|
||||
### Validation Tuning ###
|
||||
|
||||
username_regex = "^[a-z][-a-z0-9]*$"
|
||||
min_password_length = 4
|
||||
shells_file = "/etc/shells"
|
||||
privileged_group = "staff"
|
||||
notify_hook = "/etc/csc/notify-hook"
|
||||
expired_account_email = "/etc/csc/expired-account"
|
||||
mathsoc_regex = ".*(mat/|vpa/se|computer science|math).*"
|
||||
mathsoc_dont_count = "cpdohert dlgawley dtbartle mbiggs saforres tmyklebu"
|
|
@ -1,5 +0,0 @@
|
|||
# /etc/csc/kerberos.cf: CSC Kerberos Administration Configuration
|
||||
|
||||
realm = "CSCLUB.UWATERLOO.CA"
|
||||
admin_principal = "ceo/admin@CSCLUB.UWATERLOO.CA"
|
||||
admin_keytab = "/etc/csc/ceo.keytab"
|
|
@ -1,14 +0,0 @@
|
|||
# /etc/csc/ldap.cf: CSC LDAP Configuration
|
||||
|
||||
server_url = "ldaps:///"
|
||||
|
||||
users_base = "ou=People,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
groups_base = "ou=Group,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
sudo_base = "ou=SUDOers,dc=csclub,dc=uwaterloo,dc=ca"
|
||||
|
||||
admin_bind_dn =
|
||||
admin_bind_keytab = "/etc/csc/ceo.keytab"
|
||||
admin_bind_userid = "ceo"
|
||||
|
||||
sasl_mech = "GSSAPI"
|
||||
sasl_realm = "CSCLUB.UWATERLOO.CA"
|
|
@ -0,0 +1,4 @@
|
|||
# /etc/csc/library.cf: Library Config
|
||||
|
||||
library_connect_string = "postgres://librarian:PWPWPWPWPWPWPWPWPWPW@127.0.0.1/library"
|
||||
aws_account_key = "KEYKEYKEYKEYKEYKEYKY"
|
|
@ -1,5 +0,0 @@
|
|||
# /etc/csc/library.cf: Library Config
|
||||
|
||||
library_db_path = /users/office/library.db
|
||||
library_connect_string = "sqlite:///home/mgregson/csc/pyceo/test.db"
|
||||
aws_account_key = "1TNCT5S0RNDV13CJJCG2"
|
|
@ -0,0 +1 @@
|
|||
ginseng adduser 0x01
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
|
||||
name=$1
|
||||
email=$2
|
||||
shift 2
|
||||
|
||||
tmp="$(tempfile)"
|
||||
trap "rm $tmp" 0
|
||||
exec >"$tmp"
|
||||
|
||||
echo "From: Computer Science Club <ceo+expired@csclub.uwaterloo.ca>"
|
||||
echo "Reply-to: CSClub Exec <exec@csclub.uwaterloo.ca>"
|
||||
echo "To: $name <$email>"
|
||||
echo "Subject: [CSClub] Account Expiration"
|
||||
echo ""
|
||||
echo "Hello,
|
||||
|
||||
We noticed that your Computer Science Club membership has expired. We would
|
||||
like to remind you of the many benefits of being a member of the club:
|
||||
|
||||
* 4 GiB of disk quota
|
||||
* Web space
|
||||
* Email address
|
||||
* Shell account
|
||||
* Access to our library
|
||||
|
||||
If you would like to renew your membership (the fee is \$2 per term), we have
|
||||
various methods of doing so:
|
||||
|
||||
* Come by our office (MC 3036)
|
||||
* Send us a PayPal donation and send us the transaction id; see
|
||||
http://csclub.uwaterloo.ca/about/donations for details
|
||||
* Mail us a cheque; here's our address:
|
||||
Computer Science Club
|
||||
Math & Computer 3036/3037
|
||||
University of Waterloo
|
||||
200 University Avenue West
|
||||
Waterloo, ON N3L 3G1
|
||||
Canada
|
||||
|
||||
If you have any questions, feel free to contact us by phone at
|
||||
(519) 888-4567 x33870, or by email at exec@csclub.uwaterloo.ca.
|
||||
|
||||
Regards,
|
||||
|
||||
The Computer Science Club"
|
||||
|
||||
exec >&- 2>&-
|
||||
/usr/sbin/sendmail -t -f "ceo@csclub.uwaterloo.ca" < "$tmp"
|
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash -p
|
||||
|
||||
# This is a privileged script.
|
||||
IFS=$' \t\n'
|
||||
PATH=/usr/bin:/bin
|
||||
unset ENV BASH_ENV CDPATH
|
||||
umask 077
|
||||
|
||||
prog=$1
|
||||
auth=$2
|
||||
shift 2
|
||||
|
||||
tmp="$(tempfile)"
|
||||
trap "rm $tmp" 0
|
||||
exec >"$tmp"
|
||||
|
||||
authrn="$(getent passwd "$auth" | awk -F: '{ print $5 }' | sed -e 's/,.*//')"
|
||||
|
||||
h_from="$prog <ceo+$prog@csclub.uwaterloo.ca>"
|
||||
h_to="Membership and Accounts <ceo@csclub.uwaterloo.ca>"
|
||||
h_cc="$authrn <$auth@csclub.uwaterloo.ca>"
|
||||
|
||||
if test "$prog" = addmember; then
|
||||
user=$1 name=$2 dept=$3 status=$4; shift 4
|
||||
subj="New Member: $user"
|
||||
test -z "$dept" && dept="things unknown"
|
||||
body="Name: $name
|
||||
Account: $user
|
||||
Program: $dept
|
||||
Added by: $auth"
|
||||
|
||||
elif test "$prog" = addclub; then
|
||||
user=$1 name=$2 status=$4; shift 4
|
||||
subj="New Club Account: $user"
|
||||
body="Club: $name
|
||||
Account: $user
|
||||
Added by: $auth"
|
||||
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
output=$(cat)
|
||||
|
||||
if test "$status" = "failure"; then
|
||||
subj="$subj (FAILURES)"
|
||||
fi
|
||||
|
||||
echo "From: $h_from"
|
||||
echo "To: $h_to"
|
||||
echo "Cc: $h_cc"
|
||||
echo "X-Auth-User: $auth"
|
||||
echo "X-New-User: $user"
|
||||
echo "X-New-Name: $name"
|
||||
echo "Subject: $subj"
|
||||
echo
|
||||
echo "$body" | fmt -s
|
||||
echo
|
||||
|
||||
if test "$status" = "success"; then
|
||||
echo all failures went undetected
|
||||
elif test -n "$output"; then
|
||||
echo "$output"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo Your Friend,
|
||||
echo "$prog"
|
||||
|
||||
exec >&2
|
||||
env - /usr/sbin/sendmail -t -f "ceo@csclub.uwaterloo.ca" < "$tmp"
|
|
@ -1 +0,0 @@
|
|||
/* This file left intentionally blank. */
|
|
@ -1,747 +0,0 @@
|
|||
/*
|
||||
* lib/kadm5/admin.h
|
||||
*
|
||||
* Copyright 2001 by the Massachusetts Institute of Technology.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may
|
||||
* require a specific license from the United States Government.
|
||||
* It is the responsibility of any person or organization contemplating
|
||||
* export to obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. Furthermore if you modify this software you must label
|
||||
* your software as modified software and not distribute it in such a
|
||||
* fashion that it might be confused with the original M.I.T. software.
|
||||
* M.I.T. makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#ifndef __KADM5_ADMIN_H__
|
||||
#define __KADM5_ADMIN_H__
|
||||
|
||||
#if !defined(USE_KADM5_API_VERSION)
|
||||
#define USE_KADM5_API_VERSION 2
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <gssrpc/rpc.h>
|
||||
#include <krb5.h>
|
||||
#include <kdb.h>
|
||||
#include <com_err.h>
|
||||
#include <kadm5/kadm_err.h>
|
||||
#include <kadm5/chpass_util_strings.h>
|
||||
|
||||
#define KADM5_ADMIN_SERVICE "kadmin/admin"
|
||||
#define KADM5_CHANGEPW_SERVICE "kadmin/changepw"
|
||||
#define KADM5_HIST_PRINCIPAL "kadmin/history"
|
||||
|
||||
typedef krb5_principal kadm5_princ_t;
|
||||
typedef char *kadm5_policy_t;
|
||||
typedef long kadm5_ret_t;
|
||||
|
||||
#define KADM5_PW_FIRST_PROMPT \
|
||||
(error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
|
||||
#define KADM5_PW_SECOND_PROMPT \
|
||||
(error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
|
||||
|
||||
/*
|
||||
* Successful return code
|
||||
*/
|
||||
#define KADM5_OK 0
|
||||
|
||||
/*
|
||||
* Field masks
|
||||
*/
|
||||
|
||||
/* kadm5_principal_ent_t */
|
||||
#define KADM5_PRINCIPAL 0x000001
|
||||
#define KADM5_PRINC_EXPIRE_TIME 0x000002
|
||||
#define KADM5_PW_EXPIRATION 0x000004
|
||||
#define KADM5_LAST_PWD_CHANGE 0x000008
|
||||
#define KADM5_ATTRIBUTES 0x000010
|
||||
#define KADM5_MAX_LIFE 0x000020
|
||||
#define KADM5_MOD_TIME 0x000040
|
||||
#define KADM5_MOD_NAME 0x000080
|
||||
#define KADM5_KVNO 0x000100
|
||||
#define KADM5_MKVNO 0x000200
|
||||
#define KADM5_AUX_ATTRIBUTES 0x000400
|
||||
#define KADM5_POLICY 0x000800
|
||||
#define KADM5_POLICY_CLR 0x001000
|
||||
/* version 2 masks */
|
||||
#define KADM5_MAX_RLIFE 0x002000
|
||||
#define KADM5_LAST_SUCCESS 0x004000
|
||||
#define KADM5_LAST_FAILED 0x008000
|
||||
#define KADM5_FAIL_AUTH_COUNT 0x010000
|
||||
#define KADM5_KEY_DATA 0x020000
|
||||
#define KADM5_TL_DATA 0x040000
|
||||
#ifdef notyet /* Novell */
|
||||
#define KADM5_CPW_FUNCTION 0x080000
|
||||
#define KADM5_RANDKEY_USED 0x100000
|
||||
#endif
|
||||
#define KADM5_LOAD 0x200000
|
||||
|
||||
/* all but KEY_DATA and TL_DATA */
|
||||
#define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff
|
||||
|
||||
|
||||
/* kadm5_policy_ent_t */
|
||||
#define KADM5_PW_MAX_LIFE 0x004000
|
||||
#define KADM5_PW_MIN_LIFE 0x008000
|
||||
#define KADM5_PW_MIN_LENGTH 0x010000
|
||||
#define KADM5_PW_MIN_CLASSES 0x020000
|
||||
#define KADM5_PW_HISTORY_NUM 0x040000
|
||||
#define KADM5_REF_COUNT 0x080000
|
||||
|
||||
/* kadm5_config_params */
|
||||
#define KADM5_CONFIG_REALM 0x000001
|
||||
#define KADM5_CONFIG_DBNAME 0x000002
|
||||
#define KADM5_CONFIG_MKEY_NAME 0x000004
|
||||
#define KADM5_CONFIG_MAX_LIFE 0x000008
|
||||
#define KADM5_CONFIG_MAX_RLIFE 0x000010
|
||||
#define KADM5_CONFIG_EXPIRATION 0x000020
|
||||
#define KADM5_CONFIG_FLAGS 0x000040
|
||||
#define KADM5_CONFIG_ADMIN_KEYTAB 0x000080
|
||||
#define KADM5_CONFIG_STASH_FILE 0x000100
|
||||
#define KADM5_CONFIG_ENCTYPE 0x000200
|
||||
#define KADM5_CONFIG_ADBNAME 0x000400
|
||||
#define KADM5_CONFIG_ADB_LOCKFILE 0x000800
|
||||
/*#define KADM5_CONFIG_PROFILE 0x001000*/
|
||||
#define KADM5_CONFIG_ACL_FILE 0x002000
|
||||
#define KADM5_CONFIG_KADMIND_PORT 0x004000
|
||||
#define KADM5_CONFIG_ENCTYPES 0x008000
|
||||
#define KADM5_CONFIG_ADMIN_SERVER 0x010000
|
||||
#define KADM5_CONFIG_DICT_FILE 0x020000
|
||||
#define KADM5_CONFIG_MKEY_FROM_KBD 0x040000
|
||||
#define KADM5_CONFIG_KPASSWD_PORT 0x080000
|
||||
#define KADM5_CONFIG_OLD_AUTH_GSSAPI 0x100000
|
||||
#define KADM5_CONFIG_NO_AUTH 0x200000
|
||||
#define KADM5_CONFIG_AUTH_NOFALLBACK 0x400000
|
||||
#ifdef notyet /* Novell */
|
||||
#define KADM5_CONFIG_KPASSWD_SERVER 0x800000
|
||||
#endif
|
||||
/*
|
||||
* permission bits
|
||||
*/
|
||||
#define KADM5_PRIV_GET 0x01
|
||||
#define KADM5_PRIV_ADD 0x02
|
||||
#define KADM5_PRIV_MODIFY 0x04
|
||||
#define KADM5_PRIV_DELETE 0x08
|
||||
|
||||
/*
|
||||
* API versioning constants
|
||||
*/
|
||||
#define KADM5_MASK_BITS 0xffffff00
|
||||
|
||||
#define KADM5_STRUCT_VERSION_MASK 0x12345600
|
||||
#define KADM5_STRUCT_VERSION_1 (KADM5_STRUCT_VERSION_MASK|0x01)
|
||||
#define KADM5_STRUCT_VERSION KADM5_STRUCT_VERSION_1
|
||||
|
||||
#define KADM5_API_VERSION_MASK 0x12345700
|
||||
#define KADM5_API_VERSION_1 (KADM5_API_VERSION_MASK|0x01)
|
||||
#define KADM5_API_VERSION_2 (KADM5_API_VERSION_MASK|0x02)
|
||||
|
||||
typedef struct _kadm5_principal_ent_t_v2 {
|
||||
krb5_principal principal;
|
||||
krb5_timestamp princ_expire_time;
|
||||
krb5_timestamp last_pwd_change;
|
||||
krb5_timestamp pw_expiration;
|
||||
krb5_deltat max_life;
|
||||
krb5_principal mod_name;
|
||||
krb5_timestamp mod_date;
|
||||
krb5_flags attributes;
|
||||
krb5_kvno kvno;
|
||||
krb5_kvno mkvno;
|
||||
char *policy;
|
||||
long aux_attributes;
|
||||
|
||||
/* version 2 fields */
|
||||
krb5_deltat max_renewable_life;
|
||||
krb5_timestamp last_success;
|
||||
krb5_timestamp last_failed;
|
||||
krb5_kvno fail_auth_count;
|
||||
krb5_int16 n_key_data;
|
||||
krb5_int16 n_tl_data;
|
||||
krb5_tl_data *tl_data;
|
||||
krb5_key_data *key_data;
|
||||
} kadm5_principal_ent_rec_v2, *kadm5_principal_ent_t_v2;
|
||||
|
||||
typedef struct _kadm5_principal_ent_t_v1 {
|
||||
krb5_principal principal;
|
||||
krb5_timestamp princ_expire_time;
|
||||
krb5_timestamp last_pwd_change;
|
||||
krb5_timestamp pw_expiration;
|
||||
krb5_deltat max_life;
|
||||
krb5_principal mod_name;
|
||||
krb5_timestamp mod_date;
|
||||
krb5_flags attributes;
|
||||
krb5_kvno kvno;
|
||||
krb5_kvno mkvno;
|
||||
char *policy;
|
||||
long aux_attributes;
|
||||
} kadm5_principal_ent_rec_v1, *kadm5_principal_ent_t_v1;
|
||||
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
typedef struct _kadm5_principal_ent_t_v1
|
||||
kadm5_principal_ent_rec, *kadm5_principal_ent_t;
|
||||
#else
|
||||
typedef struct _kadm5_principal_ent_t_v2
|
||||
kadm5_principal_ent_rec, *kadm5_principal_ent_t;
|
||||
#endif
|
||||
|
||||
typedef struct _kadm5_policy_ent_t {
|
||||
char *policy;
|
||||
long pw_min_life;
|
||||
long pw_max_life;
|
||||
long pw_min_length;
|
||||
long pw_min_classes;
|
||||
long pw_history_num;
|
||||
long policy_refcnt;
|
||||
} kadm5_policy_ent_rec, *kadm5_policy_ent_t;
|
||||
|
||||
/*
|
||||
* Data structure returned by kadm5_get_config_params()
|
||||
*/
|
||||
typedef struct _kadm5_config_params {
|
||||
long mask;
|
||||
char * realm;
|
||||
int kadmind_port;
|
||||
int kpasswd_port;
|
||||
|
||||
char * admin_server;
|
||||
#ifdef notyet /* Novell */ /* ABI change? */
|
||||
char * kpasswd_server;
|
||||
#endif
|
||||
|
||||
char * dbname;
|
||||
char * admin_dbname;
|
||||
char * admin_lockfile;
|
||||
char * admin_keytab;
|
||||
char * acl_file;
|
||||
char * dict_file;
|
||||
|
||||
int mkey_from_kbd;
|
||||
char * stash_file;
|
||||
char * mkey_name;
|
||||
krb5_enctype enctype;
|
||||
krb5_deltat max_life;
|
||||
krb5_deltat max_rlife;
|
||||
krb5_timestamp expiration;
|
||||
krb5_flags flags;
|
||||
krb5_key_salt_tuple *keysalts;
|
||||
krb5_int32 num_keysalts;
|
||||
} kadm5_config_params;
|
||||
|
||||
/***********************************************************************
|
||||
* This is the old krb5_realm_read_params, which I mutated into
|
||||
* kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
|
||||
* still uses.
|
||||
***********************************************************************/
|
||||
|
||||
/*
|
||||
* Data structure returned by krb5_read_realm_params()
|
||||
*/
|
||||
typedef struct __krb5_realm_params {
|
||||
char * realm_profile;
|
||||
char * realm_dbname;
|
||||
char * realm_mkey_name;
|
||||
char * realm_stash_file;
|
||||
char * realm_kdc_ports;
|
||||
char * realm_kdc_tcp_ports;
|
||||
char * realm_acl_file;
|
||||
krb5_int32 realm_kadmind_port;
|
||||
krb5_enctype realm_enctype;
|
||||
krb5_deltat realm_max_life;
|
||||
krb5_deltat realm_max_rlife;
|
||||
krb5_timestamp realm_expiration;
|
||||
krb5_flags realm_flags;
|
||||
krb5_key_salt_tuple *realm_keysalts;
|
||||
unsigned int realm_reject_bad_transit:1;
|
||||
unsigned int realm_kadmind_port_valid:1;
|
||||
unsigned int realm_enctype_valid:1;
|
||||
unsigned int realm_max_life_valid:1;
|
||||
unsigned int realm_max_rlife_valid:1;
|
||||
unsigned int realm_expiration_valid:1;
|
||||
unsigned int realm_flags_valid:1;
|
||||
unsigned int realm_reject_bad_transit_valid:1;
|
||||
krb5_int32 realm_num_keysalts;
|
||||
} krb5_realm_params;
|
||||
|
||||
/*
|
||||
* functions
|
||||
*/
|
||||
|
||||
#if USE_KADM5_API_VERSION > 1
|
||||
krb5_error_code kadm5_get_config_params(krb5_context context,
|
||||
int use_kdc_config,
|
||||
kadm5_config_params *params_in,
|
||||
kadm5_config_params *params_out);
|
||||
|
||||
krb5_error_code kadm5_free_config_params(krb5_context context,
|
||||
kadm5_config_params *params);
|
||||
|
||||
krb5_error_code kadm5_free_realm_params(krb5_context kcontext,
|
||||
kadm5_config_params *params);
|
||||
|
||||
krb5_error_code kadm5_get_admin_service_name(krb5_context, char *,
|
||||
char *, size_t);
|
||||
#endif
|
||||
|
||||
kadm5_ret_t kadm5_init(char *client_name, char *pass,
|
||||
char *service_name,
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
char *realm,
|
||||
#else
|
||||
kadm5_config_params *params,
|
||||
#endif
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
kadm5_ret_t kadm5_init_with_password(char *client_name,
|
||||
char *pass,
|
||||
char *service_name,
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
char *realm,
|
||||
#else
|
||||
kadm5_config_params *params,
|
||||
#endif
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
kadm5_ret_t kadm5_init_with_skey(char *client_name,
|
||||
char *keytab,
|
||||
char *service_name,
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
char *realm,
|
||||
#else
|
||||
kadm5_config_params *params,
|
||||
#endif
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
#if USE_KADM5_API_VERSION > 1
|
||||
kadm5_ret_t kadm5_init_with_creds(char *client_name,
|
||||
krb5_ccache cc,
|
||||
char *service_name,
|
||||
kadm5_config_params *params,
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
#endif
|
||||
kadm5_ret_t kadm5_lock(void *server_handle);
|
||||
kadm5_ret_t kadm5_unlock(void *server_handle);
|
||||
kadm5_ret_t kadm5_flush(void *server_handle);
|
||||
kadm5_ret_t kadm5_destroy(void *server_handle);
|
||||
kadm5_ret_t kadm5_create_principal(void *server_handle,
|
||||
kadm5_principal_ent_t ent,
|
||||
long mask, char *pass);
|
||||
kadm5_ret_t kadm5_create_principal_3(void *server_handle,
|
||||
kadm5_principal_ent_t ent,
|
||||
long mask,
|
||||
int n_ks_tuple,
|
||||
krb5_key_salt_tuple *ks_tuple,
|
||||
char *pass);
|
||||
kadm5_ret_t kadm5_delete_principal(void *server_handle,
|
||||
krb5_principal principal);
|
||||
kadm5_ret_t kadm5_modify_principal(void *server_handle,
|
||||
kadm5_principal_ent_t ent,
|
||||
long mask);
|
||||
kadm5_ret_t kadm5_rename_principal(void *server_handle,
|
||||
krb5_principal,krb5_principal);
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
kadm5_ret_t kadm5_get_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
kadm5_principal_ent_t *ent);
|
||||
#else
|
||||
kadm5_ret_t kadm5_get_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
kadm5_principal_ent_t ent,
|
||||
long mask);
|
||||
#endif
|
||||
kadm5_ret_t kadm5_chpass_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
char *pass);
|
||||
kadm5_ret_t kadm5_chpass_principal_3(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_boolean keepold,
|
||||
int n_ks_tuple,
|
||||
krb5_key_salt_tuple *ks_tuple,
|
||||
char *pass);
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
kadm5_ret_t kadm5_randkey_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_keyblock **keyblock);
|
||||
#else
|
||||
kadm5_ret_t kadm5_randkey_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_keyblock **keyblocks,
|
||||
int *n_keys);
|
||||
kadm5_ret_t kadm5_randkey_principal_3(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_boolean keepold,
|
||||
int n_ks_tuple,
|
||||
krb5_key_salt_tuple *ks_tuple,
|
||||
krb5_keyblock **keyblocks,
|
||||
int *n_keys);
|
||||
#endif
|
||||
kadm5_ret_t kadm5_setv4key_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_keyblock *keyblock);
|
||||
|
||||
kadm5_ret_t kadm5_setkey_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_keyblock *keyblocks,
|
||||
int n_keys);
|
||||
|
||||
kadm5_ret_t kadm5_setkey_principal_3(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_boolean keepold,
|
||||
int n_ks_tuple,
|
||||
krb5_key_salt_tuple *ks_tuple,
|
||||
krb5_keyblock *keyblocks,
|
||||
int n_keys);
|
||||
|
||||
kadm5_ret_t kadm5_decrypt_key(void *server_handle,
|
||||
kadm5_principal_ent_t entry, krb5_int32
|
||||
ktype, krb5_int32 stype, krb5_int32
|
||||
kvno, krb5_keyblock *keyblock,
|
||||
krb5_keysalt *keysalt, int *kvnop);
|
||||
|
||||
kadm5_ret_t kadm5_create_policy(void *server_handle,
|
||||
kadm5_policy_ent_t ent,
|
||||
long mask);
|
||||
/*
|
||||
* kadm5_create_policy_internal is not part of the supported,
|
||||
* exposed API. It is available only in the server library, and you
|
||||
* shouldn't use it unless you know why it's there and how it's
|
||||
* different from kadm5_create_policy.
|
||||
*/
|
||||
kadm5_ret_t kadm5_create_policy_internal(void *server_handle,
|
||||
kadm5_policy_ent_t
|
||||
entry, long mask);
|
||||
kadm5_ret_t kadm5_delete_policy(void *server_handle,
|
||||
kadm5_policy_t policy);
|
||||
kadm5_ret_t kadm5_modify_policy(void *server_handle,
|
||||
kadm5_policy_ent_t ent,
|
||||
long mask);
|
||||
/*
|
||||
* kadm5_modify_policy_internal is not part of the supported,
|
||||
* exposed API. It is available only in the server library, and you
|
||||
* shouldn't use it unless you know why it's there and how it's
|
||||
* different from kadm5_modify_policy.
|
||||
*/
|
||||
kadm5_ret_t kadm5_modify_policy_internal(void *server_handle,
|
||||
kadm5_policy_ent_t
|
||||
entry, long mask);
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
kadm5_ret_t kadm5_get_policy(void *server_handle,
|
||||
kadm5_policy_t policy,
|
||||
kadm5_policy_ent_t *ent);
|
||||
#else
|
||||
kadm5_ret_t kadm5_get_policy(void *server_handle,
|
||||
kadm5_policy_t policy,
|
||||
kadm5_policy_ent_t ent);
|
||||
#endif
|
||||
kadm5_ret_t kadm5_get_privs(void *server_handle,
|
||||
long *privs);
|
||||
|
||||
kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
|
||||
krb5_principal princ,
|
||||
char *new_pw,
|
||||
char **ret_pw,
|
||||
char *msg_ret,
|
||||
unsigned int msg_len);
|
||||
|
||||
kadm5_ret_t kadm5_free_principal_ent(void *server_handle,
|
||||
kadm5_principal_ent_t
|
||||
ent);
|
||||
kadm5_ret_t kadm5_free_policy_ent(void *server_handle,
|
||||
kadm5_policy_ent_t ent);
|
||||
|
||||
kadm5_ret_t kadm5_get_principals(void *server_handle,
|
||||
char *exp, char ***princs,
|
||||
int *count);
|
||||
|
||||
kadm5_ret_t kadm5_get_policies(void *server_handle,
|
||||
char *exp, char ***pols,
|
||||
int *count);
|
||||
|
||||
#if USE_KADM5_API_VERSION > 1
|
||||
kadm5_ret_t kadm5_free_key_data(void *server_handle,
|
||||
krb5_int16 *n_key_data,
|
||||
krb5_key_data *key_data);
|
||||
#endif
|
||||
|
||||
kadm5_ret_t kadm5_free_name_list(void *server_handle, char **names,
|
||||
int count);
|
||||
|
||||
krb5_error_code kadm5_init_krb5_context (krb5_context *);
|
||||
|
||||
#if USE_KADM5_API_VERSION == 1
|
||||
/*
|
||||
* OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time
|
||||
* compatible with KADM5_API_VERSION_2. Basically, this means we have
|
||||
* to continue to provide all the old ovsec_kadm function and symbol
|
||||
* names.
|
||||
*/
|
||||
|
||||
#define OVSEC_KADM_ACLFILE "/krb5/ovsec_adm.acl"
|
||||
#define OVSEC_KADM_WORDFILE "/krb5/ovsec_adm.dict"
|
||||
|
||||
#define OVSEC_KADM_ADMIN_SERVICE "ovsec_adm/admin"
|
||||
#define OVSEC_KADM_CHANGEPW_SERVICE "ovsec_adm/changepw"
|
||||
#define OVSEC_KADM_HIST_PRINCIPAL "ovsec_adm/history"
|
||||
|
||||
typedef krb5_principal ovsec_kadm_princ_t;
|
||||
typedef krb5_keyblock ovsec_kadm_keyblock;
|
||||
typedef char *ovsec_kadm_policy_t;
|
||||
typedef long ovsec_kadm_ret_t;
|
||||
|
||||
enum ovsec_kadm_salttype { OVSEC_KADM_SALT_V4, OVSEC_KADM_SALT_NORMAL };
|
||||
enum ovsec_kadm_saltmod { OVSEC_KADM_MOD_KEEP, OVSEC_KADM_MOD_V4, OVSEC_KADM_MOD_NORMAL };
|
||||
|
||||
#define OVSEC_KADM_PW_FIRST_PROMPT \
|
||||
((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
|
||||
#define OVSEC_KADM_PW_SECOND_PROMPT \
|
||||
((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
|
||||
|
||||
/*
|
||||
* Successful return code
|
||||
*/
|
||||
#define OVSEC_KADM_OK 0
|
||||
|
||||
/*
|
||||
* Create/Modify masks
|
||||
*/
|
||||
/* principal */
|
||||
#define OVSEC_KADM_PRINCIPAL 0x000001
|
||||
#define OVSEC_KADM_PRINC_EXPIRE_TIME 0x000002
|
||||
#define OVSEC_KADM_PW_EXPIRATION 0x000004
|
||||
#define OVSEC_KADM_LAST_PWD_CHANGE 0x000008
|
||||
#define OVSEC_KADM_ATTRIBUTES 0x000010
|
||||
#define OVSEC_KADM_MAX_LIFE 0x000020
|
||||
#define OVSEC_KADM_MOD_TIME 0x000040
|
||||
#define OVSEC_KADM_MOD_NAME 0x000080
|
||||
#define OVSEC_KADM_KVNO 0x000100
|
||||
#define OVSEC_KADM_MKVNO 0x000200
|
||||
#define OVSEC_KADM_AUX_ATTRIBUTES 0x000400
|
||||
#define OVSEC_KADM_POLICY 0x000800
|
||||
#define OVSEC_KADM_POLICY_CLR 0x001000
|
||||
/* policy */
|
||||
#define OVSEC_KADM_PW_MAX_LIFE 0x004000
|
||||
#define OVSEC_KADM_PW_MIN_LIFE 0x008000
|
||||
#define OVSEC_KADM_PW_MIN_LENGTH 0x010000
|
||||
#define OVSEC_KADM_PW_MIN_CLASSES 0x020000
|
||||
#define OVSEC_KADM_PW_HISTORY_NUM 0x040000
|
||||
#define OVSEC_KADM_REF_COUNT 0x080000
|
||||
|
||||
/*
|
||||
* permission bits
|
||||
*/
|
||||
#define OVSEC_KADM_PRIV_GET 0x01
|
||||
#define OVSEC_KADM_PRIV_ADD 0x02
|
||||
#define OVSEC_KADM_PRIV_MODIFY 0x04
|
||||
#define OVSEC_KADM_PRIV_DELETE 0x08
|
||||
|
||||
/*
|
||||
* API versioning constants
|
||||
*/
|
||||
#define OVSEC_KADM_MASK_BITS 0xffffff00
|
||||
|
||||
#define OVSEC_KADM_STRUCT_VERSION_MASK 0x12345600
|
||||
#define OVSEC_KADM_STRUCT_VERSION_1 (OVSEC_KADM_STRUCT_VERSION_MASK|0x01)
|
||||
#define OVSEC_KADM_STRUCT_VERSION OVSEC_KADM_STRUCT_VERSION_1
|
||||
|
||||
#define OVSEC_KADM_API_VERSION_MASK 0x12345700
|
||||
#define OVSEC_KADM_API_VERSION_1 (OVSEC_KADM_API_VERSION_MASK|0x01)
|
||||
|
||||
|
||||
typedef struct _ovsec_kadm_principal_ent_t {
|
||||
krb5_principal principal;
|
||||
krb5_timestamp princ_expire_time;
|
||||
krb5_timestamp last_pwd_change;
|
||||
krb5_timestamp pw_expiration;
|
||||
krb5_deltat max_life;
|
||||
krb5_principal mod_name;
|
||||
krb5_timestamp mod_date;
|
||||
krb5_flags attributes;
|
||||
krb5_kvno kvno;
|
||||
krb5_kvno mkvno;
|
||||
char *policy;
|
||||
long aux_attributes;
|
||||
} ovsec_kadm_principal_ent_rec, *ovsec_kadm_principal_ent_t;
|
||||
|
||||
typedef struct _ovsec_kadm_policy_ent_t {
|
||||
char *policy;
|
||||
long pw_min_life;
|
||||
long pw_max_life;
|
||||
long pw_min_length;
|
||||
long pw_min_classes;
|
||||
long pw_history_num;
|
||||
long policy_refcnt;
|
||||
} ovsec_kadm_policy_ent_rec, *ovsec_kadm_policy_ent_t;
|
||||
|
||||
/*
|
||||
* functions
|
||||
*/
|
||||
ovsec_kadm_ret_t ovsec_kadm_init(char *client_name, char *pass,
|
||||
char *service_name, char *realm,
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
ovsec_kadm_ret_t ovsec_kadm_init_with_password(char *client_name,
|
||||
char *pass,
|
||||
char *service_name,
|
||||
char *realm,
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char ** db_args,
|
||||
void **server_handle);
|
||||
ovsec_kadm_ret_t ovsec_kadm_init_with_skey(char *client_name,
|
||||
char *keytab,
|
||||
char *service_name,
|
||||
char *realm,
|
||||
krb5_ui_4 struct_version,
|
||||
krb5_ui_4 api_version,
|
||||
char **db_args,
|
||||
void **server_handle);
|
||||
ovsec_kadm_ret_t ovsec_kadm_flush(void *server_handle);
|
||||
ovsec_kadm_ret_t ovsec_kadm_destroy(void *server_handle);
|
||||
ovsec_kadm_ret_t ovsec_kadm_create_principal(void *server_handle,
|
||||
ovsec_kadm_principal_ent_t ent,
|
||||
long mask, char *pass);
|
||||
ovsec_kadm_ret_t ovsec_kadm_delete_principal(void *server_handle,
|
||||
krb5_principal principal);
|
||||
ovsec_kadm_ret_t ovsec_kadm_modify_principal(void *server_handle,
|
||||
ovsec_kadm_principal_ent_t ent,
|
||||
long mask);
|
||||
ovsec_kadm_ret_t ovsec_kadm_rename_principal(void *server_handle,
|
||||
krb5_principal,krb5_principal);
|
||||
ovsec_kadm_ret_t ovsec_kadm_get_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
ovsec_kadm_principal_ent_t *ent);
|
||||
ovsec_kadm_ret_t ovsec_kadm_chpass_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
char *pass);
|
||||
ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle,
|
||||
krb5_principal principal,
|
||||
krb5_keyblock **keyblock);
|
||||
ovsec_kadm_ret_t ovsec_kadm_create_policy(void *server_handle,
|
||||
ovsec_kadm_policy_ent_t ent,
|
||||
long mask);
|
||||
/*
|
||||
* ovsec_kadm_create_policy_internal is not part of the supported,
|
||||
* exposed API. It is available only in the server library, and you
|
||||
* shouldn't use it unless you know why it's there and how it's
|
||||
* different from ovsec_kadm_create_policy.
|
||||
*/
|
||||
ovsec_kadm_ret_t ovsec_kadm_create_policy_internal(void *server_handle,
|
||||
ovsec_kadm_policy_ent_t
|
||||
entry, long mask);
|
||||
ovsec_kadm_ret_t ovsec_kadm_delete_policy(void *server_handle,
|
||||
ovsec_kadm_policy_t policy);
|
||||
ovsec_kadm_ret_t ovsec_kadm_modify_policy(void *server_handle,
|
||||
ovsec_kadm_policy_ent_t ent,
|
||||
long mask);
|
||||
/*
|
||||
* ovsec_kadm_modify_policy_internal is not part of the supported,
|
||||
* exposed API. It is available only in the server library, and you
|
||||
* shouldn't use it unless you know why it's there and how it's
|
||||
* different from ovsec_kadm_modify_policy.
|
||||
*/
|
||||
ovsec_kadm_ret_t ovsec_kadm_modify_policy_internal(void *server_handle,
|
||||
ovsec_kadm_policy_ent_t
|
||||
entry, long mask);
|
||||
ovsec_kadm_ret_t ovsec_kadm_get_policy(void *server_handle,
|
||||
ovsec_kadm_policy_t policy,
|
||||
ovsec_kadm_policy_ent_t *ent);
|
||||
ovsec_kadm_ret_t ovsec_kadm_get_privs(void *server_handle,
|
||||
long *privs);
|
||||
|
||||
ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle,
|
||||
krb5_principal princ,
|
||||
char *new_pw,
|
||||
char **ret_pw,
|
||||
char *msg_ret);
|
||||
|
||||
ovsec_kadm_ret_t ovsec_kadm_free_principal_ent(void *server_handle,
|
||||
ovsec_kadm_principal_ent_t
|
||||
ent);
|
||||
ovsec_kadm_ret_t ovsec_kadm_free_policy_ent(void *server_handle,
|
||||
ovsec_kadm_policy_ent_t ent);
|
||||
|
||||
ovsec_kadm_ret_t ovsec_kadm_free_name_list(void *server_handle,
|
||||
char **names, int count);
|
||||
|
||||
ovsec_kadm_ret_t ovsec_kadm_get_principals(void *server_handle,
|
||||
char *exp, char ***princs,
|
||||
int *count);
|
||||
|
||||
ovsec_kadm_ret_t ovsec_kadm_get_policies(void *server_handle,
|
||||
char *exp, char ***pols,
|
||||
int *count);
|
||||
|
||||
#define OVSEC_KADM_FAILURE KADM5_FAILURE
|
||||
#define OVSEC_KADM_AUTH_GET KADM5_AUTH_GET
|
||||
#define OVSEC_KADM_AUTH_ADD KADM5_AUTH_ADD
|
||||
#define OVSEC_KADM_AUTH_MODIFY KADM5_AUTH_MODIFY
|
||||
#define OVSEC_KADM_AUTH_DELETE KADM5_AUTH_DELETE
|
||||
#define OVSEC_KADM_AUTH_INSUFFICIENT KADM5_AUTH_INSUFFICIENT
|
||||
#define OVSEC_KADM_BAD_DB KADM5_BAD_DB
|
||||
#define OVSEC_KADM_DUP KADM5_DUP
|
||||
#define OVSEC_KADM_RPC_ERROR KADM5_RPC_ERROR
|
||||
#define OVSEC_KADM_NO_SRV KADM5_NO_SRV
|
||||
#define OVSEC_KADM_BAD_HIST_KEY KADM5_BAD_HIST_KEY
|
||||
#define OVSEC_KADM_NOT_INIT KADM5_NOT_INIT
|
||||
#define OVSEC_KADM_UNK_PRINC KADM5_UNK_PRINC
|
||||
#define OVSEC_KADM_UNK_POLICY KADM5_UNK_POLICY
|
||||
#define OVSEC_KADM_BAD_MASK KADM5_BAD_MASK
|
||||
#define OVSEC_KADM_BAD_CLASS KADM5_BAD_CLASS
|
||||
#define OVSEC_KADM_BAD_LENGTH KADM5_BAD_LENGTH
|
||||
#define OVSEC_KADM_BAD_POLICY KADM5_BAD_POLICY
|
||||
#define OVSEC_KADM_BAD_PRINCIPAL KADM5_BAD_PRINCIPAL
|
||||
#define OVSEC_KADM_BAD_AUX_ATTR KADM5_BAD_AUX_ATTR
|
||||
#define OVSEC_KADM_BAD_HISTORY KADM5_BAD_HISTORY
|
||||
#define OVSEC_KADM_BAD_MIN_PASS_LIFE KADM5_BAD_MIN_PASS_LIFE
|
||||
#define OVSEC_KADM_PASS_Q_TOOSHORT KADM5_PASS_Q_TOOSHORT
|
||||
#define OVSEC_KADM_PASS_Q_CLASS KADM5_PASS_Q_CLASS
|
||||
#define OVSEC_KADM_PASS_Q_DICT KADM5_PASS_Q_DICT
|
||||
#define OVSEC_KADM_PASS_REUSE KADM5_PASS_REUSE
|
||||
#define OVSEC_KADM_PASS_TOOSOON KADM5_PASS_TOOSOON
|
||||
#define OVSEC_KADM_POLICY_REF KADM5_POLICY_REF
|
||||
#define OVSEC_KADM_INIT KADM5_INIT
|
||||
#define OVSEC_KADM_BAD_PASSWORD KADM5_BAD_PASSWORD
|
||||
#define OVSEC_KADM_PROTECT_PRINCIPAL KADM5_PROTECT_PRINCIPAL
|
||||
#define OVSEC_KADM_BAD_SERVER_HANDLE KADM5_BAD_SERVER_HANDLE
|
||||
#define OVSEC_KADM_BAD_STRUCT_VERSION KADM5_BAD_STRUCT_VERSION
|
||||
#define OVSEC_KADM_OLD_STRUCT_VERSION KADM5_OLD_STRUCT_VERSION
|
||||
#define OVSEC_KADM_NEW_STRUCT_VERSION KADM5_NEW_STRUCT_VERSION
|
||||
#define OVSEC_KADM_BAD_API_VERSION KADM5_BAD_API_VERSION
|
||||
#define OVSEC_KADM_OLD_LIB_API_VERSION KADM5_OLD_LIB_API_VERSION
|
||||
#define OVSEC_KADM_OLD_SERVER_API_VERSION KADM5_OLD_SERVER_API_VERSION
|
||||
#define OVSEC_KADM_NEW_LIB_API_VERSION KADM5_NEW_LIB_API_VERSION
|
||||
#define OVSEC_KADM_NEW_SERVER_API_VERSION KADM5_NEW_SERVER_API_VERSION
|
||||
#define OVSEC_KADM_SECURE_PRINC_MISSING KADM5_SECURE_PRINC_MISSING
|
||||
#define OVSEC_KADM_NO_RENAME_SALT KADM5_NO_RENAME_SALT
|
||||
|
||||
#endif /* USE_KADM5_API_VERSION == 1 */
|
||||
|
||||
#endif /* __KADM5_ADMIN_H__ */
|
|
@ -1 +0,0 @@
|
|||
/* This file left intentionally blank. */
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* ettmp11037.h:
|
||||
* This file is automatically generated; please do not edit it.
|
||||
*/
|
||||
|
||||
#include <et/com_err.h>
|
||||
|
||||
#define KADM5_FAILURE (43787520L)
|
||||
#define KADM5_AUTH_GET (43787521L)
|
||||
#define KADM5_AUTH_ADD (43787522L)
|
||||
#define KADM5_AUTH_MODIFY (43787523L)
|
||||
#define KADM5_AUTH_DELETE (43787524L)
|
||||
#define KADM5_AUTH_INSUFFICIENT (43787525L)
|
||||
#define KADM5_BAD_DB (43787526L)
|
||||
#define KADM5_DUP (43787527L)
|
||||
#define KADM5_RPC_ERROR (43787528L)
|
||||
#define KADM5_NO_SRV (43787529L)
|
||||
#define KADM5_BAD_HIST_KEY (43787530L)
|
||||
#define KADM5_NOT_INIT (43787531L)
|
||||
#define KADM5_UNK_PRINC (43787532L)
|
||||
#define KADM5_UNK_POLICY (43787533L)
|
||||
#define KADM5_BAD_MASK (43787534L)
|
||||
#define KADM5_BAD_CLASS (43787535L)
|
||||
#define KADM5_BAD_LENGTH (43787536L)
|
||||
#define KADM5_BAD_POLICY (43787537L)
|
||||
#define KADM5_BAD_PRINCIPAL (43787538L)
|
||||
#define KADM5_BAD_AUX_ATTR (43787539L)
|
||||
#define KADM5_BAD_HISTORY (43787540L)
|
||||
#define KADM5_BAD_MIN_PASS_LIFE (43787541L)
|
||||
#define KADM5_PASS_Q_TOOSHORT (43787542L)
|
||||
#define KADM5_PASS_Q_CLASS (43787543L)
|
||||
#define KADM5_PASS_Q_DICT (43787544L)
|
||||
#define KADM5_PASS_REUSE (43787545L)
|
||||
#define KADM5_PASS_TOOSOON (43787546L)
|
||||
#define KADM5_POLICY_REF (43787547L)
|
||||
#define KADM5_INIT (43787548L)
|
||||
#define KADM5_BAD_PASSWORD (43787549L)
|
||||
#define KADM5_PROTECT_PRINCIPAL (43787550L)
|
||||
#define KADM5_BAD_SERVER_HANDLE (43787551L)
|
||||
#define KADM5_BAD_STRUCT_VERSION (43787552L)
|
||||
#define KADM5_OLD_STRUCT_VERSION (43787553L)
|
||||
#define KADM5_NEW_STRUCT_VERSION (43787554L)
|
||||
#define KADM5_BAD_API_VERSION (43787555L)
|
||||
#define KADM5_OLD_LIB_API_VERSION (43787556L)
|
||||
#define KADM5_OLD_SERVER_API_VERSION (43787557L)
|
||||
#define KADM5_NEW_LIB_API_VERSION (43787558L)
|
||||
#define KADM5_NEW_SERVER_API_VERSION (43787559L)
|
||||
#define KADM5_SECURE_PRINC_MISSING (43787560L)
|
||||
#define KADM5_NO_RENAME_SALT (43787561L)
|
||||
#define KADM5_BAD_CLIENT_PARAMS (43787562L)
|
||||
#define KADM5_BAD_SERVER_PARAMS (43787563L)
|
||||
#define KADM5_AUTH_LIST (43787564L)
|
||||
#define KADM5_AUTH_CHANGEPW (43787565L)
|
||||
#define KADM5_GSS_ERROR (43787566L)
|
||||
#define KADM5_BAD_TL_TYPE (43787567L)
|
||||
#define KADM5_MISSING_CONF_PARAMS (43787568L)
|
||||
#define KADM5_BAD_SERVER_NAME (43787569L)
|
||||
#define KADM5_AUTH_SETKEY (43787570L)
|
||||
#define KADM5_SETKEY_DUP_ENCTYPES (43787571L)
|
||||
#define KADM5_SETV4KEY_INVAL_ENCTYPE (43787572L)
|
||||
#define KADM5_SETKEY3_ETYPE_MISMATCH (43787573L)
|
||||
#define KADM5_MISSING_KRB5_CONF_PARAMS (43787574L)
|
||||
#define KADM5_XDR_FAILURE (43787575L)
|
||||
extern const struct error_table et_ovk_error_table;
|
||||
extern void initialize_ovk_error_table(void);
|
||||
|
||||
/* For compatibility with Heimdal */
|
||||
extern void initialize_ovk_error_table_r(struct et_list **list);
|
||||
|
||||
#define ERROR_TABLE_BASE_ovk (43787520L)
|
||||
|
||||
/* for compatibility with older versions... */
|
||||
#define init_ovk_err_tbl initialize_ovk_error_table
|
||||
#define ovk_err_base ERROR_TABLE_BASE_ovk
|
500
include/kdb.h
500
include/kdb.h
|
@ -1,500 +0,0 @@
|
|||
/*
|
||||
* include/krb5/kdb.h
|
||||
*
|
||||
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may
|
||||
* require a specific license from the United States Government.
|
||||
* It is the responsibility of any person or organization contemplating
|
||||
* export to obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. Furthermore if you modify this software you must label
|
||||
* your software as modified software and not distribute it in such a
|
||||
* fashion that it might be confused with the original M.I.T. software.
|
||||
* M.I.T. makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
*
|
||||
* KDC Database interface definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 by the FundsXpress, INC.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may require
|
||||
* a specific license from the United States Government. It is the
|
||||
* responsibility of any person or organization contemplating export to
|
||||
* obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of FundsXpress. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. FundsXpress makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef KRB5_KDB5__
|
||||
#define KRB5_KDB5__
|
||||
|
||||
/* Salt types */
|
||||
#define KRB5_KDB_SALTTYPE_NORMAL 0
|
||||
#define KRB5_KDB_SALTTYPE_V4 1
|
||||
#define KRB5_KDB_SALTTYPE_NOREALM 2
|
||||
#define KRB5_KDB_SALTTYPE_ONLYREALM 3
|
||||
#define KRB5_KDB_SALTTYPE_SPECIAL 4
|
||||
#define KRB5_KDB_SALTTYPE_AFS3 5
|
||||
|
||||
/* Attributes */
|
||||
#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
|
||||
#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
|
||||
#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
|
||||
#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
|
||||
#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
|
||||
#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
|
||||
#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
|
||||
#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
|
||||
#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
|
||||
#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
|
||||
#define KRB5_KDB_DISALLOW_SVR 0x00001000
|
||||
#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
|
||||
#define KRB5_KDB_SUPPORT_DESMD5 0x00004000
|
||||
#define KRB5_KDB_NEW_PRINC 0x00008000
|
||||
|
||||
/* Creation flags */
|
||||
#define KRB5_KDB_CREATE_BTREE 0x00000001
|
||||
#define KRB5_KDB_CREATE_HASH 0x00000002
|
||||
|
||||
/*
|
||||
* Note --- these structures cannot be modified without changing the
|
||||
* database version number in libkdb.a, but should be expandable by
|
||||
* adding new tl_data types.
|
||||
*/
|
||||
typedef struct _krb5_tl_data {
|
||||
struct _krb5_tl_data* tl_data_next; /* NOT saved */
|
||||
krb5_int16 tl_data_type;
|
||||
krb5_ui_2 tl_data_length;
|
||||
krb5_octet * tl_data_contents;
|
||||
} krb5_tl_data;
|
||||
|
||||
/*
|
||||
* If this ever changes up the version number and make the arrays be as
|
||||
* big as necessary.
|
||||
*
|
||||
* Currently the first type is the enctype and the second is the salt type.
|
||||
*/
|
||||
typedef struct _krb5_key_data {
|
||||
krb5_int16 key_data_ver; /* Version */
|
||||
krb5_int16 key_data_kvno; /* Key Version */
|
||||
krb5_int16 key_data_type[2]; /* Array of types */
|
||||
krb5_ui_2 key_data_length[2]; /* Array of lengths */
|
||||
krb5_octet * key_data_contents[2]; /* Array of pointers */
|
||||
} krb5_key_data;
|
||||
|
||||
#define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */
|
||||
|
||||
typedef struct _krb5_keysalt {
|
||||
krb5_int16 type;
|
||||
krb5_data data; /* Length, data */
|
||||
} krb5_keysalt;
|
||||
|
||||
typedef struct _krb5_db_entry_new {
|
||||
krb5_magic magic; /* NOT saved */
|
||||
krb5_ui_2 len;
|
||||
krb5_ui_4 mask; /* members currently changed/set */
|
||||
krb5_flags attributes;
|
||||
krb5_deltat max_life;
|
||||
krb5_deltat max_renewable_life;
|
||||
krb5_timestamp expiration; /* When the client expires */
|
||||
krb5_timestamp pw_expiration; /* When its passwd expires */
|
||||
krb5_timestamp last_success; /* Last successful passwd */
|
||||
krb5_timestamp last_failed; /* Last failed passwd attempt */
|
||||
krb5_kvno fail_auth_count; /* # of failed passwd attempt */
|
||||
krb5_int16 n_tl_data;
|
||||
krb5_int16 n_key_data;
|
||||
krb5_ui_2 e_length; /* Length of extra data */
|
||||
krb5_octet * e_data; /* Extra data to be saved */
|
||||
|
||||
krb5_principal princ; /* Length, data */
|
||||
krb5_tl_data * tl_data; /* Linked list */
|
||||
krb5_key_data * key_data; /* Array */
|
||||
} krb5_db_entry;
|
||||
|
||||
typedef struct _osa_policy_ent_t {
|
||||
int version;
|
||||
char *name;
|
||||
krb5_ui_4 pw_min_life;
|
||||
krb5_ui_4 pw_max_life;
|
||||
krb5_ui_4 pw_min_length;
|
||||
krb5_ui_4 pw_min_classes;
|
||||
krb5_ui_4 pw_history_num;
|
||||
krb5_ui_4 policy_refcnt;
|
||||
} osa_policy_ent_rec, *osa_policy_ent_t;
|
||||
|
||||
typedef void (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
|
||||
|
||||
typedef struct __krb5_key_salt_tuple {
|
||||
krb5_enctype ks_enctype;
|
||||
krb5_int32 ks_salttype;
|
||||
} krb5_key_salt_tuple;
|
||||
|
||||
#define KRB5_KDB_MAGIC_NUMBER 0xdbdbdbdb
|
||||
#define KRB5_KDB_V1_BASE_LENGTH 38
|
||||
|
||||
#define KRB5_TL_LAST_PWD_CHANGE 0x0001
|
||||
#define KRB5_TL_MOD_PRINC 0x0002
|
||||
#define KRB5_TL_KADM_DATA 0x0003
|
||||
#define KRB5_TL_KADM5_E_DATA 0x0004
|
||||
#define KRB5_TL_RB1_CHALLENGE 0x0005
|
||||
#ifdef SECURID
|
||||
#define KRB5_TL_SECURID_STATE 0x0006
|
||||
#define KRB5_TL_DB_ARGS 0x7fff
|
||||
#endif /* SECURID */
|
||||
#define KRB5_TL_USER_CERTIFICATE 0x0007
|
||||
|
||||
/*
|
||||
* Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set
|
||||
* on the principal.
|
||||
*/
|
||||
#define KRB5_MAX_FAIL_COUNT 5
|
||||
|
||||
/* XXX depends on knowledge of krb5_parse_name() formats */
|
||||
#define KRB5_KDB_M_NAME "K/M" /* Kerberos/Master */
|
||||
|
||||
/* prompts used by default when reading the KDC password from the keyboard. */
|
||||
#define KRB5_KDC_MKEY_1 "Enter KDC database master key"
|
||||
#define KRB5_KDC_MKEY_2 "Re-enter KDC database master key to verify"
|
||||
|
||||
|
||||
extern char *krb5_mkey_pwd_prompt1;
|
||||
extern char *krb5_mkey_pwd_prompt2;
|
||||
|
||||
/*
|
||||
* These macros specify the encoding of data within the database.
|
||||
*
|
||||
* Data encoding is little-endian.
|
||||
*/
|
||||
#include "k5-platform.h"
|
||||
#define krb5_kdb_decode_int16(cp, i16) \
|
||||
*((krb5_int16 *) &(i16)) = load_16_le(cp)
|
||||
#define krb5_kdb_decode_int32(cp, i32) \
|
||||
*((krb5_int32 *) &(i32)) = load_32_le(cp)
|
||||
#define krb5_kdb_encode_int16(i16, cp) store_16_le(i16, cp)
|
||||
#define krb5_kdb_encode_int32(i32, cp) store_32_le(i32, cp)
|
||||
|
||||
#define KRB5_KDB_OPEN_RW 0
|
||||
#define KRB5_KDB_OPEN_RO 1
|
||||
|
||||
#ifndef KRB5_KDB_SRV_TYPE_KDC
|
||||
#define KRB5_KDB_SRV_TYPE_KDC 0x0100
|
||||
#endif
|
||||
|
||||
#ifndef KRB5_KDB_SRV_TYPE_ADMIN
|
||||
#define KRB5_KDB_SRV_TYPE_ADMIN 0x0200
|
||||
#endif
|
||||
|
||||
#ifndef KRB5_KDB_SRV_TYPE_PASSWD
|
||||
#define KRB5_KDB_SRV_TYPE_PASSWD 0x0300
|
||||
#endif
|
||||
|
||||
#ifndef KRB5_KDB_SRV_TYPE_OTHER
|
||||
#define KRB5_KDB_SRV_TYPE_OTHER 0x0400
|
||||
#endif
|
||||
|
||||
#define KRB5_KDB_OPT_SET_DB_NAME 0
|
||||
#define KRB5_KDB_OPT_SET_LOCK_MODE 1
|
||||
|
||||
#define KRB5_DB_LOCKMODE_SHARED 0x0001
|
||||
#define KRB5_DB_LOCKMODE_EXCLUSIVE 0x0002
|
||||
#define KRB5_DB_LOCKMODE_DONTBLOCK 0x0004
|
||||
#define KRB5_DB_LOCKMODE_PERMANENT 0x0008
|
||||
|
||||
/* libkdb.spec */
|
||||
krb5_error_code krb5_db_open( krb5_context kcontext, char **db_args, int mode );
|
||||
krb5_error_code krb5_db_init ( krb5_context kcontext );
|
||||
krb5_error_code krb5_db_create ( krb5_context kcontext, char **db_args );
|
||||
krb5_error_code krb5_db_inited ( krb5_context kcontext );
|
||||
krb5_error_code kdb5_db_create ( krb5_context kcontext, char **db_args );
|
||||
krb5_error_code krb5_db_fini ( krb5_context kcontext );
|
||||
const char * krb5_db_errcode2string ( krb5_context kcontext, long err_code );
|
||||
krb5_error_code krb5_db_destroy ( krb5_context kcontext, char **db_args );
|
||||
krb5_error_code krb5_db_promote ( krb5_context kcontext, char **db_args );
|
||||
krb5_error_code krb5_db_get_age ( krb5_context kcontext, char *db_name, time_t *t );
|
||||
krb5_error_code krb5_db_set_option ( krb5_context kcontext, int option, void *value );
|
||||
krb5_error_code krb5_db_lock ( krb5_context kcontext, int lock_mode );
|
||||
krb5_error_code krb5_db_unlock ( krb5_context kcontext );
|
||||
krb5_error_code krb5_db_get_principal ( krb5_context kcontext,
|
||||
krb5_const_principal search_for,
|
||||
krb5_db_entry *entries,
|
||||
int *nentries,
|
||||
krb5_boolean *more );
|
||||
krb5_error_code krb5_db_free_principal ( krb5_context kcontext,
|
||||
krb5_db_entry *entry,
|
||||
int count );
|
||||
krb5_error_code krb5_db_put_principal ( krb5_context kcontext,
|
||||
krb5_db_entry *entries,
|
||||
int *nentries);
|
||||
krb5_error_code krb5_db_delete_principal ( krb5_context kcontext,
|
||||
krb5_principal search_for,
|
||||
int *nentries );
|
||||
krb5_error_code krb5_db_iterate ( krb5_context kcontext,
|
||||
char *match_entry,
|
||||
int (*func) (krb5_pointer, krb5_db_entry *),
|
||||
krb5_pointer func_arg );
|
||||
krb5_error_code krb5_supported_realms ( krb5_context kcontext,
|
||||
char **realms );
|
||||
krb5_error_code krb5_free_supported_realms ( krb5_context kcontext,
|
||||
char **realms );
|
||||
krb5_error_code krb5_db_set_master_key_ext ( krb5_context kcontext,
|
||||
char *pwd,
|
||||
krb5_keyblock *key );
|
||||
krb5_error_code krb5_db_set_mkey ( krb5_context context,
|
||||
krb5_keyblock *key);
|
||||
krb5_error_code krb5_db_get_mkey ( krb5_context kcontext,
|
||||
krb5_keyblock **key );
|
||||
krb5_error_code krb5_db_free_master_key ( krb5_context kcontext,
|
||||
krb5_keyblock *key );
|
||||
krb5_error_code krb5_db_store_master_key ( krb5_context kcontext,
|
||||
char *db_arg,
|
||||
krb5_principal mname,
|
||||
krb5_keyblock *key,
|
||||
char *master_pwd);
|
||||
krb5_error_code krb5_db_fetch_mkey ( krb5_context context,
|
||||
krb5_principal mname,
|
||||
krb5_enctype etype,
|
||||
krb5_boolean fromkeyboard,
|
||||
krb5_boolean twice,
|
||||
char *db_args,
|
||||
krb5_data *salt,
|
||||
krb5_keyblock *key);
|
||||
krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext,
|
||||
krb5_principal mprinc,
|
||||
krb5_keyblock *mkey );
|
||||
krb5_error_code
|
||||
krb5_dbe_find_enctype( krb5_context kcontext,
|
||||
krb5_db_entry *dbentp,
|
||||
krb5_int32 ktype,
|
||||
krb5_int32 stype,
|
||||
krb5_int32 kvno,
|
||||
krb5_key_data **kdatap);
|
||||
|
||||
|
||||
krb5_error_code krb5_dbe_search_enctype ( krb5_context kcontext,
|
||||
krb5_db_entry *dbentp,
|
||||
krb5_int32 *start,
|
||||
krb5_int32 ktype,
|
||||
krb5_int32 stype,
|
||||
krb5_int32 kvno,
|
||||
krb5_key_data **kdatap);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_setup_mkey_name ( krb5_context context,
|
||||
const char *keyname,
|
||||
const char *realm,
|
||||
char **fullname,
|
||||
krb5_principal *principal);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbekd_decrypt_key_data( krb5_context context,
|
||||
const krb5_keyblock * mkey,
|
||||
const krb5_key_data * key_data,
|
||||
krb5_keyblock * dbkey,
|
||||
krb5_keysalt * keysalt);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbekd_encrypt_key_data( krb5_context context,
|
||||
const krb5_keyblock * mkey,
|
||||
const krb5_keyblock * dbkey,
|
||||
const krb5_keysalt * keysalt,
|
||||
int keyver,
|
||||
krb5_key_data * key_data);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_lookup_mod_princ_data( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_timestamp * mod_time,
|
||||
krb5_principal * mod_princ);
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_update_last_pwd_change( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_timestamp stamp);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_lookup_tl_data( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_tl_data * ret_tl_data);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_create_key_data( krb5_context context,
|
||||
krb5_db_entry * entry);
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_update_mod_princ_data( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_timestamp mod_date,
|
||||
krb5_const_principal mod_princ);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_update_last_pwd_change( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_timestamp stamp);
|
||||
|
||||
void *krb5_db_alloc( krb5_context kcontext,
|
||||
void *ptr,
|
||||
size_t size );
|
||||
|
||||
void krb5_db_free( krb5_context kcontext,
|
||||
void *ptr);
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_lookup_last_pwd_change( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_timestamp * stamp);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_update_tl_data( krb5_context context,
|
||||
krb5_db_entry * entry,
|
||||
krb5_tl_data * new_tl_data);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_cpw( krb5_context kcontext,
|
||||
krb5_keyblock * master_key,
|
||||
krb5_key_salt_tuple * ks_tuple,
|
||||
int ks_tuple_count,
|
||||
char * passwd,
|
||||
int new_kvno,
|
||||
krb5_boolean keepold,
|
||||
krb5_db_entry * db_entry);
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_ark( krb5_context context,
|
||||
krb5_keyblock * master_key,
|
||||
krb5_key_salt_tuple * ks_tuple,
|
||||
int ks_tuple_count,
|
||||
krb5_db_entry * db_entry);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_crk( krb5_context context,
|
||||
krb5_keyblock * master_key,
|
||||
krb5_key_salt_tuple * ks_tuple,
|
||||
int ks_tuple_count,
|
||||
krb5_boolean keepold,
|
||||
krb5_db_entry * db_entry);
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_apw( krb5_context context,
|
||||
krb5_keyblock * master_key,
|
||||
krb5_key_salt_tuple * ks_tuple,
|
||||
int ks_tuple_count,
|
||||
char * passwd,
|
||||
krb5_db_entry * db_entry);
|
||||
|
||||
/* default functions. Should not be directly called */
|
||||
/*
|
||||
* Default functions prototype
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_def_search_enctype( krb5_context kcontext,
|
||||
krb5_db_entry *dbentp,
|
||||
krb5_int32 *start,
|
||||
krb5_int32 ktype,
|
||||
krb5_int32 stype,
|
||||
krb5_int32 kvno,
|
||||
krb5_key_data **kdatap);
|
||||
|
||||
krb5_error_code
|
||||
krb5_def_store_mkey( krb5_context context,
|
||||
char *keyfile,
|
||||
krb5_principal mname,
|
||||
krb5_keyblock *key,
|
||||
char *master_pwd);
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_def_fetch_mkey( krb5_context context,
|
||||
krb5_principal mname,
|
||||
krb5_keyblock *key,
|
||||
int *kvno,
|
||||
char *db_args);
|
||||
|
||||
krb5_error_code
|
||||
krb5_def_verify_master_key( krb5_context context,
|
||||
krb5_principal mprinc,
|
||||
krb5_keyblock *mkey);
|
||||
|
||||
krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
|
||||
char *pwd,
|
||||
krb5_keyblock *key );
|
||||
|
||||
krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
|
||||
krb5_keyblock **key );
|
||||
|
||||
krb5_error_code
|
||||
krb5_dbe_def_cpw( krb5_context context,
|
||||
krb5_keyblock * master_key,
|
||||
krb5_key_salt_tuple * ks_tuple,
|
||||
int ks_tuple_count,
|
||||
char * passwd,
|
||||
int new_kvno,
|
||||
krb5_boolean keepold,
|
||||
krb5_db_entry * db_entry);
|
||||
|
||||
krb5_error_code
|
||||
krb5_def_promote_db(krb5_context, char *, char **);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_create_policy( krb5_context kcontext,
|
||||
osa_policy_ent_t policy);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_get_policy ( krb5_context kcontext,
|
||||
char *name,
|
||||
osa_policy_ent_t *policy,
|
||||
int *nentries);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_put_policy( krb5_context kcontext,
|
||||
osa_policy_ent_t policy);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_iter_policy( krb5_context kcontext,
|
||||
char *match_entry,
|
||||
osa_adb_iter_policy_func func,
|
||||
void *data);
|
||||
|
||||
krb5_error_code
|
||||
krb5_db_delete_policy( krb5_context kcontext,
|
||||
char *policy);
|
||||
|
||||
void
|
||||
krb5_db_free_policy( krb5_context kcontext,
|
||||
osa_policy_ent_t policy);
|
||||
|
||||
#define KRB5_KDB_DEF_FLAGS 0
|
||||
|
||||
#endif /* KRB5_KDB5__ */
|
|
@ -3,5 +3,11 @@
|
|||
.nfs*
|
||||
/addmember
|
||||
/addclub
|
||||
/adduser
|
||||
/op-adduser
|
||||
/zfsaddhomedir
|
||||
/config-test
|
||||
/ceod
|
||||
/ceoc
|
||||
/ceo.pb-c.c
|
||||
/ceo.pb-c.h
|
||||
|
|
74
src/Makefile
74
src/Makefile
|
@ -1,53 +1,79 @@
|
|||
CFLAGS := -g3 -O2 -Wall -Werror -DDEBUG
|
||||
LDFLAGS := -L/opt/csw/lib -Wl,-R/opt/csw/lib -L/usr/local/lib -Wl,-R/usr/local/lib
|
||||
INCLUDES := -I../include $(shell krb5-config --cflags)
|
||||
override LDFLAGS += -std=gnu99 $(INCLUDES)
|
||||
LDFLAGS := -Wl,--as-needed
|
||||
INCLUDES := $(shell krb5-config --cflags)
|
||||
override CFLAGS += -std=gnu99 $(INCLUDES)
|
||||
|
||||
DESTDIR :=
|
||||
PREFIX := /usr/local
|
||||
|
||||
BIN_PROGS := addmember addclub zfsaddhomedir simpleaddhomedir
|
||||
BIN_PROGS := addmember addclub ceod
|
||||
LIB_PROGS := ceoc op-adduser
|
||||
EXT_PROGS := config-test
|
||||
|
||||
LIBCEO_OBJECTS := common.o addhomedir.o
|
||||
LIBCEO_LDFLAGS :=
|
||||
LIBCEO_PROGS := addmember addclub
|
||||
LDAP_OBJECTS := ldap.o
|
||||
LDAP_LDFLAGS := -lldap
|
||||
LDAP_PROGS := addmember addclub
|
||||
LDAP_LIBS := -lldap
|
||||
LDAP_PROGS := addmember addclub op-adduser
|
||||
KRB5_OBJECTS := krb5.o kadm.o
|
||||
KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client)
|
||||
KRB5_PROGS := addmember addclub
|
||||
KRB5_LIBS := $(shell krb5-config --libs krb5 kadm-client)
|
||||
KRB5_PROGS := addmember addclub op-adduser
|
||||
HOME_OBJECTS := homedir.o
|
||||
HOME_LIBS := -lacl
|
||||
HOME_PROGS := op-adduser
|
||||
NET_OBJECTS := net.o gss.o ops.o
|
||||
NET_LIBS := -lsctp $(shell krb5-config --libs gssapi)
|
||||
NET_PROGS := ceod ceoc
|
||||
PROTO_OBJECTS := ceo.pb-c.o
|
||||
PROTO_LIBS := -lprotobuf-c
|
||||
PROTO_PROGS := op-adduser addmember addclub
|
||||
CONFIG_OBJECTS := config.o parser.o
|
||||
CONFIG_LDFLAGS :=
|
||||
CONFIG_PROGS := $(OLDCEO_PROGS) $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS)
|
||||
CONFIG_LIBS :=
|
||||
CONFIG_PROGS := $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS)
|
||||
UTIL_OBJECTS := util.o strbuf.o
|
||||
UTIL_PROGS := config-test zfsaddhomedir simpleaddhomedir $(CONFIG_PROGS)
|
||||
UTIL_PROGS := config-test $(CONFIG_PROGS)
|
||||
|
||||
all: $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS)
|
||||
|
||||
clean:
|
||||
rm -f $(BIN_PROGS) $(EXT_PROGS) *.o
|
||||
rm -f $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) *.o ceo.pb-c.c ceo.pb-c.h
|
||||
|
||||
op-adduser.o addmember.o addclub.o: ceo.pb-c.h
|
||||
|
||||
ceo.pb-c.c ceo.pb-c.h: ceo.proto
|
||||
protoc-c --c_out=. ceo.proto
|
||||
|
||||
ceod: dmaster.o dslave.o
|
||||
$(CC) $(LDFLAGS) $^ $(CFLAGS) $(LDLIBS) -o $@
|
||||
|
||||
config-test: config-test.o parser.o
|
||||
|
||||
config.o: config.h config-vars.h
|
||||
|
||||
install:
|
||||
install -d $(DESTDIR)$(PREFIX)/bin
|
||||
install_clients:
|
||||
install -d $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib/ceod
|
||||
install addmember addclub $(DESTDIR)$(PREFIX)/bin
|
||||
install ceoc $(DESTDIR)$(PREFIX)/lib/ceod
|
||||
|
||||
$(LIBCEO_PROGS): LDFLAGS += $(LIBCEO_LDFLAGS)
|
||||
$(LIBCEO_PROGS): $(LIBCEO_OBJECTS)
|
||||
$(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS)
|
||||
install_daemon:
|
||||
install -d $(DESTDIR)$(PREFIX)/sbin $(DESTDIR)$(PREFIX)/lib/ceod
|
||||
install ceod $(DESTDIR)$(PREFIX)/sbin
|
||||
install op-adduser $(DESTDIR)$(PREFIX)/lib/ceod
|
||||
|
||||
install: install_clients install_daemon
|
||||
|
||||
$(NET_PROGS): LDLIBS += $(NET_LIBS)
|
||||
$(NET_PROGS): $(NET_OBJECTS)
|
||||
$(LDAP_PROGS): LDLIBS += $(LDAP_LIBS)
|
||||
$(LDAP_PROGS): $(LDAP_OBJECTS)
|
||||
$(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS)
|
||||
$(KRB5_PROGS): LDLIBS += $(KRB5_LIBS)
|
||||
$(KRB5_PROGS): $(KRB5_OBJECTS)
|
||||
$(CONFIG_PROGS): LDFLAGS += $(CONFIG_LDFLAGS)
|
||||
$(HOME_PROGS): LDLIBS += $(HOME_LIBS)
|
||||
$(HOME_PROGS): $(HOME_OBJECTS)
|
||||
$(PROTO_PROGS): LDLIBS += $(PROTO_LIBS)
|
||||
$(PROTO_PROGS): $(PROTO_OBJECTS)
|
||||
$(CONFIG_PROGS): LDLIBS += $(CONFIG_LIBS)
|
||||
$(CONFIG_PROGS): $(CONFIG_OBJECTS)
|
||||
$(UTIL_PROGS): LDFLAGS += $(UTIL_LDFLAGS)
|
||||
$(UTIL_PROGS): LDLIBS += $(UTIL_LIBS)
|
||||
$(UTIL_PROGS): $(UTIL_OBJECTS)
|
||||
|
||||
.PHONY: clean all
|
||||
.SECONDARY: zfsaddhomedir.o addmember.o addclub.o simpleaddhomedir.o
|
||||
.SECONDARY: ceoc.o addmember.o addclub.o
|
||||
|
|
161
src/addclub.c
161
src/addclub.c
|
@ -12,159 +12,81 @@
|
|||
#include <syslog.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "ldap.h"
|
||||
#include "krb5.h"
|
||||
#include "kadm.h"
|
||||
#include "addhomedir.h"
|
||||
#include "ceo.pb-c.h"
|
||||
|
||||
char *prog = NULL;
|
||||
char *user = NULL;
|
||||
int privileged = 0;
|
||||
|
||||
static int force = 0;
|
||||
static int no_notify = 0;
|
||||
|
||||
static char *name = NULL;
|
||||
static char *userid = NULL;
|
||||
|
||||
static struct option opts[] = {
|
||||
{ "force", 0, NULL, 'f' },
|
||||
{ "no-notify", 0, NULL, 'q' },
|
||||
{ NULL, 0, NULL, '\0' },
|
||||
};
|
||||
|
||||
const char *default_lib_dir = "/usr/lib/ceod";
|
||||
const char *lib_dir;
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "Usage: %s userid clubname\n", prog);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int addclub() {
|
||||
int krb_ok, user_ok, group_ok, sudo_ok, home_ok;
|
||||
int id;
|
||||
char homedir[1024];
|
||||
char acl_s[1024] = {0};
|
||||
int addclub(void) {
|
||||
struct strbuf preq = STRBUF_INIT;
|
||||
struct strbuf pret = STRBUF_INIT;
|
||||
char cpath[1024];
|
||||
char *cargv[] = { "ceoc", "adduser", NULL };
|
||||
|
||||
notice("adding uid=%s cn=%s by %s", userid, name, user);
|
||||
if (snprintf(cpath, sizeof(cpath), "%s/ceoc", lib_dir) >= sizeof(cpath))
|
||||
fatal("path too long");
|
||||
|
||||
if (setreuid(0, 0))
|
||||
fatalpe("setreuid");
|
||||
if (setregid(0, 0))
|
||||
fatalpe("setregid");
|
||||
Ceo__AddUser req;
|
||||
ceo__add_user__init(&req);
|
||||
|
||||
if (!force && getpwnam(userid) != NULL)
|
||||
deny("user %s already exists", userid);
|
||||
req.username = userid;
|
||||
req.realname = name;
|
||||
req.type = CEO__ADD_USER__TYPE__CLUB;
|
||||
|
||||
snprintf(homedir, sizeof(homedir), "%s/%s", club_home, userid);
|
||||
ceo_krb5_init();
|
||||
ceo_ldap_init();
|
||||
ceo_kadm_init();
|
||||
strbuf_grow(&preq, ceo__add_user__get_packed_size(&req));
|
||||
strbuf_setlen(&preq, ceo__add_user__pack(&req, (uint8_t *)preq.buf));
|
||||
|
||||
if (ceo_user_exists(userid))
|
||||
deny("user %s already exists in LDAP", userid);
|
||||
if (ceo_group_exists(userid))
|
||||
deny("group %s already exists in LDAP", userid);
|
||||
if (spawnvem(cpath, cargv, environ, &preq, &pret, 0))
|
||||
return 1;
|
||||
|
||||
if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0)
|
||||
fatal("no available uids in range [%zd, %zd]", club_min_id, club_max_id);
|
||||
Ceo__AddUserResponse *ret = ceo__add_user_response__unpack(&protobuf_c_default_allocator,
|
||||
pret.len, (uint8_t *)pret.buf);
|
||||
if (!ret)
|
||||
fatal("failed to unpack response");
|
||||
|
||||
snprintf(acl_s, sizeof(acl_s), club_home_acl, userid);
|
||||
|
||||
krb_ok = ceo_del_princ(userid);
|
||||
if (!krb_ok)
|
||||
notice("successfully cleared principal for %s", userid);
|
||||
|
||||
user_ok = krb_ok || ceo_add_user(userid, users_base, "club", name, homedir,
|
||||
club_shell, id, NULL);
|
||||
if (!user_ok)
|
||||
notice("successfully created account for %s", userid);
|
||||
|
||||
group_ok = user_ok || ceo_add_group(userid, groups_base, id);
|
||||
if (!group_ok)
|
||||
notice("successfully created group for %s", userid);
|
||||
|
||||
sudo_ok = user_ok || ceo_add_group_sudo(userid, sudo_base);
|
||||
if (!sudo_ok)
|
||||
notice("successfully added group sudo entry for %s", userid);
|
||||
|
||||
home_ok = user_ok || ceo_create_home(homedir, refquota, id, id, homedir_mode, acl_s);
|
||||
if (!home_ok)
|
||||
notice("successfully created home directory for %s", userid);
|
||||
|
||||
notice("done uid=%s", userid);
|
||||
|
||||
if (!no_notify && !user_ok) {
|
||||
int pid;
|
||||
int hkp[2];
|
||||
FILE *hkf;
|
||||
int status;
|
||||
|
||||
if (pipe(hkp))
|
||||
errorpe("pipe");
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (!pid) {
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
close(hkp[1]);
|
||||
dup2(hkp[0], 0);
|
||||
exit(execl(notify_hook, notify_hook, prog, user, userid, name, NULL));
|
||||
}
|
||||
|
||||
hkf = fdopen(hkp[1], "w");
|
||||
|
||||
if (group_ok)
|
||||
fprintf(hkf, "failed to create group\n");
|
||||
if (home_ok)
|
||||
fprintf(hkf, "failed to create home directory\n");
|
||||
if (!group_ok && !home_ok)
|
||||
fprintf(hkf, "all failures went undetected\n");
|
||||
|
||||
fclose(hkf);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status))
|
||||
notice("hook %s exited with status %d", notify_hook, WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
notice("hook %s killed by signal %d", notify_hook, WTERMSIG(status));
|
||||
for (int i = 0; i < ret->n_messages; i++) {
|
||||
if (ret->messages[i]->status)
|
||||
error("%s", ret->messages[i]->message);
|
||||
else
|
||||
notice("%s", ret->messages[i]->message);
|
||||
}
|
||||
|
||||
ceo_kadm_cleanup();
|
||||
ceo_ldap_cleanup();
|
||||
ceo_krb5_cleanup();
|
||||
ceo__add_user_response__free_unpacked(ret, &protobuf_c_default_allocator);
|
||||
strbuf_release(&preq);
|
||||
strbuf_release(&pret);
|
||||
|
||||
return krb_ok || user_ok || group_ok || home_ok;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int opt;
|
||||
int ret;
|
||||
|
||||
prog = basename(argv[0]);
|
||||
init_log(prog, LOG_PID, LOG_AUTHPRIV);
|
||||
prog = xstrdup(basename(argv[0]));
|
||||
init_log(prog, 0, LOG_AUTHPRIV);
|
||||
|
||||
configure();
|
||||
|
||||
user = ceo_get_user();
|
||||
privileged = ceo_get_privileged();
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
if (!privileged)
|
||||
deny("not privileged enough to force");
|
||||
force = 1;
|
||||
break;
|
||||
case 'q':
|
||||
if (!privileged)
|
||||
deny("not privileged enough to suppress notifications");
|
||||
no_notify = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
|
@ -173,11 +95,18 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (argc - optind != 2)
|
||||
if (argc - optind != 2 && argc - optind != 3)
|
||||
usage();
|
||||
|
||||
userid = argv[optind++];
|
||||
name = argv[optind++];
|
||||
|
||||
return addclub();
|
||||
lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir;
|
||||
|
||||
ret = addclub();
|
||||
|
||||
free_config();
|
||||
free(prog);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/acl.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "addhomedir.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
#include "krb5.h"
|
||||
|
||||
int ceo_create_home(char *homedir, char *refquota, uid_t uid, gid_t gid, char *mode, char *acl) {
|
||||
char uid_str[16], gid_str[16];
|
||||
char *zfs_argv[] = { "ssh", "ceo@ginseng", "/usr/sbin/simpleaddhomedir", \
|
||||
homedir, skeleton_dir, uid_str, gid_str, mode, NULL };
|
||||
int ret = 0;
|
||||
|
||||
assert(homedir[0]);
|
||||
snprintf(uid_str, sizeof(uid_str), "%ld", (long)uid);
|
||||
snprintf(gid_str, sizeof(gid_str), "%ld", (long)uid);
|
||||
if(!acl[0]) acl = NULL;
|
||||
|
||||
ceo_krb5_auth(admin_bind_userid, admin_bind_keytab);
|
||||
if(spawnv("/usr/bin/ssh", zfs_argv)) {
|
||||
errorpe("failed calling simpleaddhomedir for %s", homedir);
|
||||
ret = -1;
|
||||
}
|
||||
ceo_krb5_deauth();
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
int ceo_create_home(char *, char *, uid_t, gid_t, char *, char *);
|
165
src/addmember.c
165
src/addmember.c
|
@ -12,19 +12,13 @@
|
|||
#include <syslog.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "ldap.h"
|
||||
#include "krb5.h"
|
||||
#include "kadm.h"
|
||||
#include "addhomedir.h"
|
||||
#include "ceo.pb-c.h"
|
||||
|
||||
char *prog = NULL;
|
||||
char *user = NULL;
|
||||
int privileged = 0;
|
||||
|
||||
static int force = 0;
|
||||
static int no_notify = 0;
|
||||
|
||||
static int use_stdin = 0;
|
||||
|
||||
|
@ -34,148 +28,78 @@ static char *program = NULL;
|
|||
static char password[1024];
|
||||
|
||||
static struct option opts[] = {
|
||||
{ "force", 0, NULL, 'f' },
|
||||
{ "no-notify", 0, NULL, 'q' },
|
||||
{ "stdin", 0, NULL, 's' },
|
||||
{ NULL, 0, NULL, '\0' },
|
||||
};
|
||||
|
||||
const char *default_lib_dir = "/usr/lib/ceod";
|
||||
const char *lib_dir;
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "Usage: %s userid realname [program]\n", prog);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int addmember() {
|
||||
int krb_ok, user_ok, group_ok, home_ok;
|
||||
int id;
|
||||
char homedir[1024];
|
||||
char acl_s[1024] = {0};
|
||||
int addmember(void) {
|
||||
struct strbuf preq = STRBUF_INIT;
|
||||
struct strbuf pret = STRBUF_INIT;
|
||||
char cpath[1024];
|
||||
char *cargv[] = { "ceoc", "adduser", NULL };
|
||||
|
||||
notice("adding uid=%s cn=%s program=%s by %s", userid, name, program, user);
|
||||
|
||||
if (setreuid(0, 0))
|
||||
fatalpe("setreuid");
|
||||
if (setregid(0, 0))
|
||||
fatalpe("setregid");
|
||||
|
||||
if (!force && getpwnam(userid) != NULL)
|
||||
deny("user %s already exists", userid);
|
||||
|
||||
snprintf(homedir, sizeof(homedir), "%s/%s", member_home, userid);
|
||||
if (snprintf(cpath, sizeof(cpath), "%s/ceoc", lib_dir) >= sizeof(cpath))
|
||||
fatal("path too long");
|
||||
|
||||
if (ceo_read_password(password, sizeof(password), use_stdin))
|
||||
return 1;
|
||||
|
||||
ceo_krb5_init();
|
||||
ceo_ldap_init();
|
||||
ceo_kadm_init();
|
||||
Ceo__AddUser req;
|
||||
ceo__add_user__init(&req);
|
||||
|
||||
if (ceo_user_exists(userid))
|
||||
deny("user %s already exists in LDAP", userid);
|
||||
if (ceo_group_exists(userid))
|
||||
deny("group %s already exists in LDAP", userid);
|
||||
req.username = userid;
|
||||
req.password = password;
|
||||
req.program = program;
|
||||
req.realname = name;
|
||||
req.type = CEO__ADD_USER__TYPE__MEMBER;
|
||||
|
||||
if ((id = ceo_new_uid(member_min_id, member_max_id)) <= 0)
|
||||
fatal("no available uids in range [%zd, %zd]", member_min_id, member_max_id);
|
||||
strbuf_grow(&preq, ceo__add_user__get_packed_size(&req));
|
||||
strbuf_setlen(&preq, ceo__add_user__pack(&req, (uint8_t *)preq.buf));
|
||||
|
||||
if (*member_home_acl) {
|
||||
snprintf(acl_s, sizeof(acl_s), member_home_acl, userid);
|
||||
if (spawnvem(cpath, cargv, environ, &preq, &pret, 0))
|
||||
return 1;
|
||||
|
||||
Ceo__AddUserResponse *ret = ceo__add_user_response__unpack(&protobuf_c_default_allocator,
|
||||
pret.len, (uint8_t *)pret.buf);
|
||||
if (!ret)
|
||||
fatal("failed to unpack response");
|
||||
|
||||
for (int i = 0; i < ret->n_messages; i++) {
|
||||
if (ret->messages[i]->status)
|
||||
error("%s", ret->messages[i]->message);
|
||||
else
|
||||
notice("%s", ret->messages[i]->message);
|
||||
}
|
||||
|
||||
krb_ok = ceo_del_princ(userid);
|
||||
krb_ok = krb_ok || ceo_add_princ(userid, password);
|
||||
if (!krb_ok)
|
||||
notice("successfully created principal for %s", userid);
|
||||
ceo__add_user_response__free_unpacked(ret, &protobuf_c_default_allocator);
|
||||
strbuf_release(&preq);
|
||||
strbuf_release(&pret);
|
||||
|
||||
user_ok = krb_ok || ceo_add_user(userid, users_base, "member", name, homedir,
|
||||
member_shell, id, "program", program, NULL);
|
||||
if (!user_ok)
|
||||
notice("successfully created account for %s", userid);
|
||||
|
||||
group_ok = user_ok || ceo_add_group(userid, groups_base, id);
|
||||
if (!group_ok)
|
||||
notice("successfully created group for %s", userid);
|
||||
|
||||
home_ok = user_ok || ceo_create_home(homedir, refquota, id, id, homedir_mode, acl_s);
|
||||
if (!home_ok)
|
||||
notice("successfully created home directory for %s", userid);
|
||||
|
||||
notice("done uid=%s", userid);
|
||||
|
||||
if (!no_notify && !user_ok) {
|
||||
int pid;
|
||||
int hkp[2];
|
||||
FILE *hkf;
|
||||
int status;
|
||||
|
||||
if (pipe(hkp))
|
||||
errorpe("pipe");
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (!pid) {
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
close(hkp[1]);
|
||||
dup2(hkp[0], 0);
|
||||
exit(execl(notify_hook, notify_hook, prog, user, userid, name, program, NULL));
|
||||
}
|
||||
|
||||
hkf = fdopen(hkp[1], "w");
|
||||
|
||||
if (group_ok)
|
||||
fprintf(hkf, "failed to create group\n");
|
||||
if (home_ok)
|
||||
fprintf(hkf, "failed to create home directory\n");
|
||||
if (!group_ok && !home_ok)
|
||||
fprintf(hkf, "all failures went undetected\n");
|
||||
|
||||
fclose(hkf);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status))
|
||||
notice("hook %s exited with status %d", notify_hook, WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
notice("hook %s killed by signal %d", notify_hook, WTERMSIG(status));
|
||||
}
|
||||
|
||||
ceo_kadm_cleanup();
|
||||
ceo_ldap_cleanup();
|
||||
ceo_krb5_cleanup();
|
||||
|
||||
return krb_ok || user_ok || group_ok || home_ok;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int opt;
|
||||
int ret;
|
||||
|
||||
prog = basename(argv[0]);
|
||||
init_log(prog, LOG_PID, LOG_AUTHPRIV);
|
||||
prog = xstrdup(basename(argv[0]));
|
||||
init_log(prog, 0, LOG_AUTHPRIV);
|
||||
|
||||
configure();
|
||||
|
||||
user = ceo_get_user();
|
||||
privileged = ceo_get_privileged();
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
use_stdin = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (!privileged)
|
||||
deny("not privileged enough to force");
|
||||
force = 1;
|
||||
break;
|
||||
case 'q':
|
||||
if (!privileged)
|
||||
deny("not privileged enough to suppress notifications");
|
||||
no_notify = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
|
@ -193,5 +117,12 @@ int main(int argc, char *argv[]) {
|
|||
if (argc - optind)
|
||||
program = argv[optind++];
|
||||
|
||||
return addmember();
|
||||
lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir;
|
||||
|
||||
ret = addmember();
|
||||
|
||||
free_config();
|
||||
free(prog);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package ceo;
|
||||
|
||||
message StatusMessage {
|
||||
required int32 status = 1;
|
||||
required string message = 2;
|
||||
}
|
||||
|
||||
message AddUser {
|
||||
enum Type {
|
||||
MEMBER = 1;
|
||||
CLUB = 2;
|
||||
}
|
||||
|
||||
required Type type = 1;
|
||||
required string username = 2;
|
||||
optional string password = 3;
|
||||
optional string realname = 4;
|
||||
optional string program = 5;
|
||||
}
|
||||
|
||||
message AddUserResponse {
|
||||
repeated StatusMessage messages = 1;
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "net.h"
|
||||
#include "gss.h"
|
||||
#include "ops.h"
|
||||
#include "config.h"
|
||||
|
||||
char *prog = NULL;
|
||||
|
||||
static struct option opts[] = {
|
||||
{ NULL, 0, NULL, '\0' },
|
||||
};
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "Usage: %s op\n", prog);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void send_gss_token(int sock, struct sockaddr *addr, socklen_t addrlen, gss_buffer_t token) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
|
||||
if (sctp_sendmsg(sock, token->value, token->length,
|
||||
addr, addrlen, MSG_AUTH, 0, 0, 0, 0) < 0)
|
||||
fatalpe("sctp_sendmsg");
|
||||
|
||||
maj_stat = gss_release_buffer(&min_stat, token);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_buffer", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
static void client_gss_auth(int sock, struct sockaddr *addr, socklen_t addrlen) {
|
||||
gss_buffer_desc incoming_tok, outgoing_tok;
|
||||
struct sctp_meta msg_meta;
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
int complete;
|
||||
|
||||
complete = initial_client_token(&outgoing_tok);
|
||||
|
||||
for (;;) {
|
||||
if (outgoing_tok.length)
|
||||
send_gss_token(sock, addr, addrlen, &outgoing_tok);
|
||||
else if (!complete)
|
||||
fatal("no token to send during auth");
|
||||
|
||||
if (complete)
|
||||
break;
|
||||
|
||||
if (!receive_one_message(sock, &msg_meta, &msg))
|
||||
fatal("connection closed during auth");
|
||||
|
||||
if (msg_meta.sinfo.sinfo_ppid != MSG_AUTH)
|
||||
fatal("unexpected message type 0x%x", msg_meta.sinfo.sinfo_ppid);
|
||||
|
||||
incoming_tok.value = msg.buf;
|
||||
incoming_tok.length = msg.len;
|
||||
|
||||
complete = process_client_token(&incoming_tok, &outgoing_tok);
|
||||
}
|
||||
|
||||
strbuf_release(&msg);
|
||||
}
|
||||
|
||||
void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) {
|
||||
const char *hostname = op->hostname;
|
||||
int sock = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
|
||||
struct sockaddr_in addr;
|
||||
struct sctp_meta response_meta;
|
||||
|
||||
if (!in->len)
|
||||
fatal("no data to send");
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(9987);
|
||||
addr.sin_addr = op->addr;
|
||||
|
||||
struct sctp_event_subscribe events;
|
||||
memset(&events, 0, sizeof(events));
|
||||
events.sctp_data_io_event = 1;
|
||||
events.sctp_association_event = 1;
|
||||
events.sctp_address_event = 1;
|
||||
events.sctp_send_failure_event = 1;
|
||||
events.sctp_peer_error_event = 1;
|
||||
events.sctp_shutdown_event = 1;
|
||||
events.sctp_partial_delivery_event = 1;
|
||||
events.sctp_adaptation_layer_event = 1;
|
||||
|
||||
if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)))
|
||||
fatalpe("setsockopt");
|
||||
|
||||
client_acquire_creds("ceod", hostname);
|
||||
client_gss_auth(sock, (sa *)&addr, sizeof(addr));
|
||||
|
||||
if (sctp_sendmsg(sock, in->buf, in->len, (struct sockaddr *)&addr,
|
||||
sizeof(addr), op->id, 0, 0, 0, 0) < 0)
|
||||
fatalpe("sctp_sendmsg");
|
||||
|
||||
if (!receive_one_message(sock, &response_meta, out))
|
||||
fatal("no response received for op %s", op->name);
|
||||
|
||||
if (response_meta.sinfo.sinfo_ppid != op->id)
|
||||
fatal("wrong ppid from server: expected %d got %d", op->id, response_meta.sinfo.sinfo_ppid);
|
||||
|
||||
if (sctp_sendmsg(sock, NULL, 0, (struct sockaddr *)&addr,
|
||||
sizeof(addr), 0, SCTP_EOF, 0, 0 ,0) < 0)
|
||||
fatalpe("sctp_sendmsg");
|
||||
}
|
||||
|
||||
int client_main(char *op_name) {
|
||||
struct op *op = find_op(op_name);
|
||||
|
||||
if (!op)
|
||||
fatal("no such op: %s", op_name);
|
||||
|
||||
struct strbuf in = STRBUF_INIT;
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
|
||||
if (strbuf_read(&in, STDIN_FILENO, 0) < 0)
|
||||
fatalpe("read");
|
||||
|
||||
run_remote(op, &in, &out);
|
||||
|
||||
if (strbuf_write(&out, STDOUT_FILENO) < 0)
|
||||
fatalpe("write");
|
||||
|
||||
strbuf_release(&in);
|
||||
strbuf_release(&out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int opt;
|
||||
int ret;
|
||||
char *op;
|
||||
|
||||
prog = xstrdup(basename(argv[0]));
|
||||
init_log(prog, 0, LOG_USER);
|
||||
|
||||
configure();
|
||||
setup_ops();
|
||||
setup_fqdn();
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
fatal("error parsing arguments");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind != 1)
|
||||
usage();
|
||||
|
||||
op = argv[optind++];
|
||||
|
||||
ret = client_main(op);
|
||||
|
||||
free_gss();
|
||||
free_fqdn();
|
||||
free_config();
|
||||
free_ops();
|
||||
free(prog);
|
||||
|
||||
return ret;
|
||||
}
|
58
src/common.c
58
src/common.c
|
@ -1,58 +0,0 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
|
||||
int ceo_get_privileged() {
|
||||
int uid = getuid();
|
||||
|
||||
// root is privileged
|
||||
if (!uid)
|
||||
return 1;
|
||||
|
||||
if (privileged_group) {
|
||||
struct group *privgrp = getgrnam(privileged_group);
|
||||
int pgid;
|
||||
gid_t grps[128];
|
||||
int count, i;
|
||||
if (!privgrp)
|
||||
return 0;
|
||||
pgid = privgrp->gr_gid;
|
||||
|
||||
count = getgroups(sizeof(grps)/sizeof(*grps), grps);
|
||||
for (i = 0; i < count; i++)
|
||||
if (grps[i] == pgid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ceo_get_user() {
|
||||
struct passwd *pwent = getpwuid(getuid());
|
||||
if (pwent == NULL)
|
||||
fatal("could not determine user");
|
||||
return xstrdup(pwent->pw_name);
|
||||
}
|
||||
|
||||
void ceo_notify_hook(int argc, ...) {
|
||||
va_list args;
|
||||
char **argv;
|
||||
int i = 0;
|
||||
|
||||
va_start(args, argc);
|
||||
|
||||
argv = (char **)xmalloc(sizeof(char *) * (argc + 1));
|
||||
|
||||
while (i < argc)
|
||||
argv[i++] = va_arg(args, char *);
|
||||
|
||||
argv[i++] = NULL;
|
||||
spawnv(notify_hook, argv);
|
||||
|
||||
va_end(args);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
int ceo_get_privileged();
|
||||
char *ceo_get_user();
|
||||
void ceo_notify_hook(int, ...);
|
|
@ -1,33 +1,24 @@
|
|||
CONFIG_STR(server_url)
|
||||
|
||||
CONFIG_STR(users_base)
|
||||
CONFIG_STR(groups_base)
|
||||
CONFIG_STR(sudo_base)
|
||||
|
||||
CONFIG_STR(skeleton_dir)
|
||||
CONFIG_STR(homedir_mode)
|
||||
CONFIG_STR(refquota)
|
||||
|
||||
CONFIG_STR(member_shell)
|
||||
CONFIG_INT(member_min_id)
|
||||
CONFIG_INT(member_max_id)
|
||||
CONFIG_STR(member_home)
|
||||
CONFIG_STR(member_home_acl)
|
||||
CONFIG_STR(member_home_skel)
|
||||
|
||||
CONFIG_STR(club_shell)
|
||||
CONFIG_INT(club_min_id)
|
||||
CONFIG_INT(club_max_id)
|
||||
CONFIG_STR(club_home)
|
||||
CONFIG_STR(club_home_acl)
|
||||
CONFIG_STR(club_home_skel)
|
||||
|
||||
CONFIG_STR(notify_hook)
|
||||
|
||||
CONFIG_STR(realm)
|
||||
CONFIG_STR(krb5_realm)
|
||||
CONFIG_STR(krb5_admin_principal)
|
||||
|
||||
CONFIG_STR(admin_principal)
|
||||
CONFIG_STR(admin_keytab)
|
||||
|
||||
CONFIG_STR(admin_bind_userid)
|
||||
CONFIG_STR(admin_bind_keytab)
|
||||
|
||||
CONFIG_STR(privileged_group)
|
||||
CONFIG_STR(ldap_server_url)
|
||||
CONFIG_STR(ldap_users_base)
|
||||
CONFIG_STR(ldap_groups_base)
|
||||
CONFIG_STR(ldap_sudo_base)
|
||||
CONFIG_STR(ldap_sasl_mech)
|
||||
CONFIG_STR(ldap_sasl_realm)
|
||||
CONFIG_STR(ldap_admin_principal)
|
||||
|
|
11
src/config.c
11
src/config.c
|
@ -54,7 +54,7 @@ void config_var(char *var, char *val) {
|
|||
}
|
||||
}
|
||||
|
||||
void configure() {
|
||||
void configure(void) {
|
||||
int i;
|
||||
char conffile[1024];
|
||||
|
||||
|
@ -80,3 +80,12 @@ void configure() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_config(void) {
|
||||
for (int i = 0; i < sizeof(config_vars)/sizeof(*config_vars); i++) {
|
||||
if (config_vars[i].type == CONFIG_TYPE_STR) {
|
||||
free(*(char **)config_vars[i].p);
|
||||
*(char **)config_vars[i].p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#undef CONFIG_STR
|
||||
#undef CONFIG_INT
|
||||
|
||||
void configure();
|
||||
void configure(void);
|
||||
void free_config(void);
|
||||
|
||||
extern const char *config_dir;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/* dmain.c */
|
||||
extern int terminate;
|
||||
extern int fatal_signal;
|
||||
|
||||
/* dslave.c */
|
||||
void slave_main(int sock, struct sockaddr *addr);
|
||||
void setup_slave(void);
|
||||
|
||||
/* builtin-adduser.c */
|
||||
extern void builtin_adduser(struct sctp_meta *in, struct sctp_meta *out);
|
|
@ -0,0 +1,183 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <alloca.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "net.h"
|
||||
#include "config.h"
|
||||
#include "gss.h"
|
||||
#include "daemon.h"
|
||||
#include "ldap.h"
|
||||
#include "kadm.h"
|
||||
#include "krb5.h"
|
||||
#include "ops.h"
|
||||
|
||||
static struct option opts[] = {
|
||||
{ "detach", 0, NULL, 'd' },
|
||||
{ NULL, 0, NULL, '\0' },
|
||||
};
|
||||
|
||||
char *prog = NULL;
|
||||
|
||||
int terminate = 0;
|
||||
int fatal_signal;
|
||||
|
||||
static int detach = 0;
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "Usage: %s [--detach]\n", prog);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
if (sig == SIGTERM || sig == SIGINT) {
|
||||
const char *s = (sig == SIGTERM) ? "terminated" : "interrupt";
|
||||
notice("shutting down (%s)", s);
|
||||
terminate = 1;
|
||||
fatal_signal = sig;
|
||||
signal(sig, SIG_DFL);
|
||||
} else if (sig == SIGSEGV) {
|
||||
error("segmentation fault");
|
||||
signal(sig, SIG_DFL);
|
||||
raise(sig);
|
||||
} else if (sig != SIGCHLD) {
|
||||
fatal("unhandled signal %d", sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_signals(void) {
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = signal_handler;
|
||||
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
}
|
||||
|
||||
static void setup_daemon(void) {
|
||||
if (chdir("/"))
|
||||
fatalpe("chdir('/')");
|
||||
if (detach) {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
fatalpe("fork");
|
||||
if (pid)
|
||||
exit(0);
|
||||
if (setsid() < 0)
|
||||
fatalpe("setsid");
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_auth(void) {
|
||||
if (setenv("KRB5CCNAME", "MEMORY:ceod", 1))
|
||||
fatalpe("setenv");
|
||||
server_acquire_creds("ceod");
|
||||
}
|
||||
|
||||
static void accept_one_client(int server) {
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
memset(&addr, 0, addrlen);
|
||||
|
||||
int client = accept(server, (sa *)&addr, &addrlen);
|
||||
if (client < 0) {
|
||||
if (errno == EINTR)
|
||||
return;
|
||||
fatalpe("accept");
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (!pid) {
|
||||
close(server);
|
||||
slave_main(client, (sa *)&addr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(client);
|
||||
}
|
||||
|
||||
static int master_main(void) {
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(9987);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
|
||||
if (sock < 0)
|
||||
fatalpe("socket");
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
|
||||
fatalpe("bind");
|
||||
|
||||
if (listen(sock, 128))
|
||||
fatalpe("listen");
|
||||
|
||||
setup_daemon();
|
||||
setup_fqdn();
|
||||
setup_signals();
|
||||
setup_auth();
|
||||
setup_ops();
|
||||
|
||||
notice("now accepting connections");
|
||||
|
||||
while (!terminate)
|
||||
accept_one_client(sock);
|
||||
|
||||
free_gss();
|
||||
free_fqdn();
|
||||
free_ops();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int opt;
|
||||
int ret;
|
||||
|
||||
prog = xstrdup(basename(argv[0]));
|
||||
init_log(prog, LOG_PID, LOG_DAEMON);
|
||||
|
||||
configure();
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
detach = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
fatal("error parsing arguments");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != optind)
|
||||
usage();
|
||||
|
||||
ret = master_main();
|
||||
|
||||
free_config();
|
||||
free(prog);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <alloca.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "strbuf.h"
|
||||
#include "net.h"
|
||||
#include "config.h"
|
||||
#include "gss.h"
|
||||
#include "daemon.h"
|
||||
#include "ldap.h"
|
||||
#include "kadm.h"
|
||||
#include "krb5.h"
|
||||
#include "ops.h"
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
if (sig == SIGSEGV) {
|
||||
error("segmentation fault");
|
||||
signal(sig, SIG_DFL);
|
||||
raise(sig);
|
||||
} else if (sig != SIGCHLD) {
|
||||
fatal("unhandled signal %d", sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_slave_sigs(void) {
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = signal_handler;
|
||||
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (terminate)
|
||||
raise(fatal_signal);
|
||||
}
|
||||
|
||||
static void setup_client(int client, struct sockaddr *addr) {
|
||||
struct sctp_event_subscribe events;
|
||||
memset(&events, 0, sizeof(events));
|
||||
events.sctp_data_io_event = 1;
|
||||
events.sctp_address_event = 1;
|
||||
events.sctp_send_failure_event = 1;
|
||||
events.sctp_peer_error_event = 1;
|
||||
events.sctp_partial_delivery_event = 1;
|
||||
events.sctp_adaptation_layer_event = 1;
|
||||
|
||||
if (setsockopt(client, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)))
|
||||
fatalpe("setsockopt(SCTP_EVENTS)");
|
||||
}
|
||||
|
||||
static void handle_auth_message(struct strbuf *in, struct strbuf *out) {
|
||||
gss_buffer_desc incoming_tok, outgoing_tok;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
|
||||
incoming_tok.value = in->buf;
|
||||
incoming_tok.length = in->len;
|
||||
|
||||
process_server_token(&incoming_tok, &outgoing_tok);
|
||||
|
||||
strbuf_add(out, outgoing_tok.value, outgoing_tok.length);
|
||||
|
||||
if (outgoing_tok.length) {
|
||||
maj_stat = gss_release_buffer(&min_stat, &outgoing_tok);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_buffer", maj_stat, min_stat);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf *out) {
|
||||
struct op *op = get_local_op(in_type);
|
||||
char *envp[16];
|
||||
|
||||
debug("running op: %s", op->name);
|
||||
|
||||
if (!op->name)
|
||||
fatal("operation %x does not exist", in_type);
|
||||
|
||||
/* TEMPORARY */
|
||||
if (!client_username())
|
||||
fatal("unathenticated");
|
||||
|
||||
make_env(envp, "LANG", "C", "CEO_USER", client_username(),
|
||||
"CEO_CONFIG_DIR", config_dir, NULL);
|
||||
char *argv[] = { op->path, NULL, };
|
||||
|
||||
if (spawnvem(op->path, argv, envp, in, out, 0))
|
||||
fatal("child %s failed", op->path);
|
||||
|
||||
free_env(envp);
|
||||
}
|
||||
|
||||
static void handle_one_message(int sock, struct sctp_meta *in_meta, struct strbuf *in) {
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
uint32_t ppid = in_meta->sinfo.sinfo_ppid;
|
||||
|
||||
if (ppid == MSG_AUTH)
|
||||
handle_auth_message(in, &out);
|
||||
else
|
||||
handle_op_message(ppid, in, &out);
|
||||
|
||||
if (out.len && sctp_sendmsg(sock, out.buf, out.len,
|
||||
(sa *)&in_meta->from, in_meta->fromlen, ppid,
|
||||
0, 0, 0, 0) < 0)
|
||||
fatalpe("sctp_sendmsg");
|
||||
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
void slave_main(int sock, struct sockaddr *addr) {
|
||||
char addrstr[INET_ADDRSTRLEN];
|
||||
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
|
||||
struct sctp_meta msg_meta;
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
|
||||
if (addr->sa_family != AF_INET)
|
||||
fatal("unsupported address family %d", addr->sa_family);
|
||||
|
||||
if (!inet_ntop(AF_INET, &addr_in->sin_addr, addrstr, sizeof(addrstr)))
|
||||
fatalpe("inet_ntop");
|
||||
|
||||
notice("accepted connection from %s", addrstr);
|
||||
|
||||
setup_slave_sigs();
|
||||
setup_client(sock, addr);
|
||||
|
||||
while (!terminate) {
|
||||
if (!receive_one_message(sock, &msg_meta, &msg))
|
||||
break;
|
||||
handle_one_message(sock, &msg_meta, &msg);
|
||||
}
|
||||
|
||||
notice("connection closed by peer %s", addrstr);
|
||||
|
||||
strbuf_release(&msg);
|
||||
|
||||
/* stuff allocated by dmaster */
|
||||
free_gss();
|
||||
free_config();
|
||||
free_fqdn();
|
||||
free_ops();
|
||||
free(prog);
|
||||
}
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "gss.h"
|
||||
#include "net.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
static gss_cred_id_t my_creds = GSS_C_NO_CREDENTIAL;
|
||||
static gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
|
||||
static gss_name_t peer_name = GSS_C_NO_NAME;
|
||||
static gss_name_t imported_service = GSS_C_NO_NAME;
|
||||
static char *peer_principal;
|
||||
static char *peer_username;
|
||||
static OM_uint32 ret_flags;
|
||||
static int complete;
|
||||
char service_name[128];
|
||||
|
||||
void free_gss(void) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
|
||||
if (peer_name) {
|
||||
maj_stat = gss_release_name(&min_stat, &peer_name);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_name", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
if (imported_service) {
|
||||
maj_stat = gss_release_name(&min_stat, &imported_service);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_name", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
if (context_handle) {
|
||||
maj_stat = gss_delete_sec_context(&min_stat, &context_handle, GSS_C_NO_BUFFER);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_delete_sec_context", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
if (my_creds) {
|
||||
maj_stat = gss_release_cred(&min_stat, &my_creds);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_creds", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
free(peer_principal);
|
||||
free(peer_username);
|
||||
}
|
||||
|
||||
static void display_status(char *prefix, OM_uint32 code, int type) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc msg;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
|
||||
maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,
|
||||
&msg_ctx, &msg);
|
||||
logmsg(LOG_ERR, "%s: %s", prefix, (char *)msg.value);
|
||||
gss_release_buffer(&min_stat, &msg);
|
||||
|
||||
while (msg_ctx) {
|
||||
maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,
|
||||
&msg_ctx, &msg);
|
||||
logmsg(LOG_ERR, "additional: %s", (char *)msg.value);
|
||||
gss_release_buffer(&min_stat, &msg);
|
||||
}
|
||||
}
|
||||
|
||||
void gss_fatal(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) {
|
||||
logmsg(LOG_ERR, "fatal: %s", msg);
|
||||
display_status("major", maj_stat, GSS_C_GSS_CODE);
|
||||
display_status("minor", min_stat, GSS_C_MECH_CODE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void import_service(const char *service, const char *hostname) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc buf_desc;
|
||||
|
||||
if (snprintf(service_name, sizeof(service_name),
|
||||
"%s@%s", service, hostname) >= sizeof(service_name))
|
||||
fatal("service name too long");
|
||||
|
||||
buf_desc.value = service_name;
|
||||
buf_desc.length = strlen(service_name);
|
||||
|
||||
maj_stat = gss_import_name(&min_stat, &buf_desc,
|
||||
GSS_C_NT_HOSTBASED_SERVICE, &imported_service);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_import_name", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
static void check_services(OM_uint32 flags) {
|
||||
debug("gss services: %sconf %sinteg %smutual %sreplay %ssequence",
|
||||
flags & GSS_C_CONF_FLAG ? "+" : "-",
|
||||
flags & GSS_C_INTEG_FLAG ? "+" : "-",
|
||||
flags & GSS_C_MUTUAL_FLAG ? "+" : "-",
|
||||
flags & GSS_C_REPLAY_FLAG ? "+" : "-",
|
||||
flags & GSS_C_SEQUENCE_FLAG ? "+" : "-");
|
||||
if (~flags & GSS_C_CONF_FLAG)
|
||||
fatal("confidentiality service required");
|
||||
if (~flags & GSS_C_INTEG_FLAG)
|
||||
fatal("integrity service required");
|
||||
if (~flags & GSS_C_MUTUAL_FLAG)
|
||||
fatal("mutual authentication required");
|
||||
}
|
||||
|
||||
void server_acquire_creds(const char *service) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
OM_uint32 time_rec;
|
||||
|
||||
if (!strlen(fqdn.buf))
|
||||
fatal("empty fqdn");
|
||||
|
||||
import_service(service, fqdn.buf);
|
||||
|
||||
notice("acquiring credentials for %s", service_name);
|
||||
|
||||
maj_stat = gss_acquire_cred(&min_stat, imported_service, GSS_C_INDEFINITE,
|
||||
GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &my_creds,
|
||||
NULL, &time_rec);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_acquire_cred", maj_stat, min_stat);
|
||||
|
||||
if (time_rec != GSS_C_INDEFINITE)
|
||||
fatal("credentials valid for %d seconds (oops)", time_rec);
|
||||
}
|
||||
|
||||
void client_acquire_creds(const char *service, const char *hostname) {
|
||||
import_service(service, hostname);
|
||||
}
|
||||
|
||||
static char *princ_to_username(char *princ) {
|
||||
char *ret = xstrdup(princ);
|
||||
char *c = strchr(ret, '@');
|
||||
if (c)
|
||||
*c = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
int process_server_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
OM_uint32 time_rec;
|
||||
gss_OID name_type;
|
||||
gss_buffer_desc peer_princ;
|
||||
|
||||
if (complete)
|
||||
fatal("unexpected %zd-byte token from peer", incoming_tok->length);
|
||||
|
||||
maj_stat = gss_accept_sec_context(&min_stat, &context_handle, my_creds,
|
||||
incoming_tok, GSS_C_NO_CHANNEL_BINDINGS, &peer_name, NULL,
|
||||
outgoing_tok, &ret_flags, &time_rec, NULL);
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
check_services(ret_flags);
|
||||
|
||||
complete = 1;
|
||||
|
||||
maj_stat = gss_display_name(&min_stat, peer_name, &peer_princ, &name_type);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_display_name", maj_stat, min_stat);
|
||||
|
||||
peer_principal = xstrdup((char *)peer_princ.value);
|
||||
peer_username = princ_to_username((char *)peer_princ.value);
|
||||
|
||||
notice("client authenticated as %s", peer_principal);
|
||||
debug("context expires in %d seconds", time_rec);
|
||||
|
||||
maj_stat = gss_release_buffer(&min_stat, &peer_princ);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_fatal("gss_release_buffer", maj_stat, min_stat);
|
||||
|
||||
} else if (maj_stat != GSS_S_CONTINUE_NEEDED) {
|
||||
gss_fatal("gss_accept_sec_context", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
return complete;
|
||||
}
|
||||
|
||||
int process_client_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok) {
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
OM_uint32 time_rec;
|
||||
gss_OID_desc krb5 = *gss_mech_krb5;
|
||||
|
||||
if (complete)
|
||||
fatal("unexpected token from peer");
|
||||
|
||||
maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &context_handle,
|
||||
imported_service, &krb5, GSS_C_MUTUAL_FLAG |
|
||||
GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
|
||||
GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS,
|
||||
incoming_tok, NULL, outgoing_tok, &ret_flags,
|
||||
&time_rec);
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
notice("server authenticated as %s", service_name);
|
||||
notice("context expires in %d seconds", time_rec);
|
||||
|
||||
check_services(ret_flags);
|
||||
|
||||
complete = 1;
|
||||
|
||||
} else if (maj_stat != GSS_S_CONTINUE_NEEDED) {
|
||||
gss_fatal("gss_init_sec_context", maj_stat, min_stat);
|
||||
}
|
||||
|
||||
return complete;
|
||||
}
|
||||
|
||||
int initial_client_token(gss_buffer_t outgoing_tok) {
|
||||
return process_client_token(GSS_C_NO_BUFFER, outgoing_tok);
|
||||
}
|
||||
|
||||
char *client_principal(void) {
|
||||
return peer_principal;
|
||||
}
|
||||
|
||||
char *client_username(void) {
|
||||
return peer_username;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include <gssapi/gssapi.h>
|
||||
#include <gssapi/gssapi_krb5.h>
|
||||
|
||||
void server_acquire_creds(const char *service);
|
||||
void client_acquire_creds(const char *service, const char *hostname);
|
||||
void gss_fatal(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat);
|
||||
int process_server_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok);
|
||||
int process_client_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok);
|
||||
int initial_client_token(gss_buffer_t outgoing_tok);
|
||||
char *client_principal(void);
|
||||
char *client_username(void);
|
||||
void free_gss(void);
|
|
@ -1,63 +1,43 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/acl.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "homedir.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 6) {
|
||||
fprintf(stderr, "Usage: simpleaddhomedir homedir skeldir uid gid mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *homedir = argv[1];
|
||||
char *skeldir = argv[2];
|
||||
uid_t uid, gid;
|
||||
char *mkdir_bin = "/bin/mkdir";
|
||||
char *chmod_bin = "/bin/chmod";
|
||||
char *dataset = homedir;
|
||||
char *create_argv[] = { "mkdir", dataset, NULL };
|
||||
char *mode_argv[] = { "chmod", "0755", homedir, NULL };
|
||||
DIR *skel;
|
||||
int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid) {
|
||||
int mask;
|
||||
DIR *skeldir;
|
||||
struct dirent *skelent;
|
||||
|
||||
assert(homedir[0]);
|
||||
uid = atol(argv[3]);
|
||||
gid = atol(argv[4]);
|
||||
mask = umask(0);
|
||||
|
||||
if (setreuid(0, 0))
|
||||
fatalpe("ogawd");
|
||||
|
||||
if(spawnv(mkdir_bin, create_argv))
|
||||
return 1;
|
||||
//Quotas are ignored now, or so I'm told.
|
||||
/* if(spawnv(zfs_bin, quota_argv)) */
|
||||
/* return 1; */
|
||||
if(spawnv(chmod_bin, mode_argv))
|
||||
return 1;
|
||||
//Fuck ACLs. The instructions I got didn't include them.
|
||||
/* if(acl && spawnv(chmod_bin, acl_argv)) */
|
||||
/* return 1; */
|
||||
|
||||
skel = opendir(skeldir);
|
||||
if (!skel) {
|
||||
errorpe("failed to open %s", skeldir);
|
||||
if (mkdir(homedir, 0755)) {
|
||||
errorpe("failed to create %s", homedir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((skelent = readdir(skel))) {
|
||||
skeldir = opendir(skel);
|
||||
if (!skeldir) {
|
||||
errorpe("failed to open %s", skel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((skelent = readdir(skeldir))) {
|
||||
struct stat sb;
|
||||
char src[PATH_MAX], dest[PATH_MAX];
|
||||
|
||||
if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, ".."))
|
||||
continue;
|
||||
|
||||
snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name);
|
||||
snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name);
|
||||
snprintf(src, sizeof(src), "%s/%s", skel, skelent->d_name);
|
||||
snprintf(dest, sizeof(dest), "%s/%s", homedir, skelent->d_name);
|
||||
lstat(src, &sb);
|
||||
|
||||
if (sb.st_uid || sb.st_gid) {
|
||||
|
@ -95,6 +75,7 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fchown(destfd, uid, gid))
|
||||
errorpe("chown: %s", dest);
|
||||
|
||||
|
@ -127,12 +108,14 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
closedir(skel);
|
||||
closedir(skeldir);
|
||||
|
||||
if (chown(homedir, uid, gid)) {
|
||||
errorpe("failed to chown %s", homedir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
umask(mask);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#include <sys/acl.h>
|
||||
|
||||
int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid);
|
19
src/kadm.c
19
src/kadm.c
|
@ -14,35 +14,40 @@ void ceo_kadm_init() {
|
|||
kadm5_config_params params;
|
||||
memset((void *) ¶ms, 0, sizeof(params));
|
||||
|
||||
retval = kadm5_init_with_skey(admin_principal, admin_keytab,
|
||||
debug("kadmin: initializing using keytab for %s", krb5_admin_principal);
|
||||
|
||||
retval = kadm5_init_with_skey(krb5_admin_principal, NULL,
|
||||
KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION,
|
||||
KADM5_API_VERSION_2, NULL, &handle);
|
||||
if (retval) {
|
||||
if (retval || !handle) {
|
||||
com_err(prog, retval, "while initializing kadm5");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void ceo_kadm_cleanup() {
|
||||
debug("kadmin: cleaning up");
|
||||
kadm5_destroy(handle);
|
||||
}
|
||||
|
||||
int ceo_add_princ(char *user, char *password) {
|
||||
krb5_error_code retval;
|
||||
kadm5_principal_ent_rec princ;
|
||||
krb5_principal princ;
|
||||
memset((void *) &princ, 0, sizeof(princ));
|
||||
|
||||
if ((retval = krb5_parse_name(context, user, &princ.principal))) {
|
||||
debug("kadmin: adding principal %s", user);
|
||||
|
||||
if ((retval = krb5_parse_name(context, user, &princ))) {
|
||||
com_err(prog, retval, "while parsing principal name");
|
||||
return retval;
|
||||
}
|
||||
|
||||
if ((retval = kadm5_create_principal(handle, &princ, KADM5_PRINCIPAL, password))) {
|
||||
if ((retval = kadm5_chpass_principal(handle, princ, password))) {
|
||||
com_err(prog, retval, "while creating principal");
|
||||
return retval;
|
||||
}
|
||||
|
||||
krb5_free_principal(context, princ.principal);
|
||||
krb5_free_principal(context, princ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,6 +55,8 @@ int ceo_del_princ(char *user) {
|
|||
krb5_error_code retval;
|
||||
krb5_principal princ;
|
||||
|
||||
debug("kadmin: deleting principal %s", user);
|
||||
|
||||
if ((retval = krb5_parse_name(context, user, &princ))) {
|
||||
com_err(prog, retval, "while parsing principal name");
|
||||
return retval;
|
||||
|
|
21
src/krb5.c
21
src/krb5.c
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <krb5.h>
|
||||
#include <syslog.h>
|
||||
|
||||
|
@ -34,36 +35,36 @@ void ceo_krb5_init() {
|
|||
|
||||
set_com_err_hook(com_err_hk);
|
||||
|
||||
debug("krb5: initializing context");
|
||||
|
||||
retval = krb5_init_context(&context);
|
||||
if (retval)
|
||||
com_err(prog, retval, "while initializing krb5");
|
||||
|
||||
retval = krb5_set_default_realm(context, realm);
|
||||
retval = krb5_set_default_realm(context, krb5_realm);
|
||||
if (retval)
|
||||
com_err(prog, retval, "while setting default realm");
|
||||
}
|
||||
|
||||
void ceo_krb5_auth(char *principal, char *ktname) {
|
||||
void ceo_krb5_auth(char *principal) {
|
||||
krb5_error_code retval;
|
||||
krb5_creds creds;
|
||||
krb5_principal princ;
|
||||
krb5_keytab keytab;
|
||||
krb5_ccache cache;
|
||||
krb5_get_init_creds_opt options;
|
||||
|
||||
krb5_get_init_creds_opt_init(&options);
|
||||
memset(&creds, 0, sizeof(creds));
|
||||
|
||||
debug("krb5: getting TGT using keytab for %s", principal);
|
||||
|
||||
if ((retval = krb5_parse_name(context, principal, &princ)))
|
||||
com_err(prog, retval, "while resolving user %s", admin_bind_userid);
|
||||
com_err(prog, retval, "while resolving user %s", principal);
|
||||
|
||||
if ((retval = krb5_cc_default(context, &cache)))
|
||||
com_err(prog, retval, "while resolving credentials cache");
|
||||
|
||||
if ((retval = krb5_kt_resolve(context, ktname, &keytab)))
|
||||
com_err(prog, retval, "while resolving keytab %s", admin_bind_keytab);
|
||||
|
||||
if ((retval = krb5_get_init_creds_keytab(context, &creds, princ, keytab, 0, NULL, &options)))
|
||||
if ((retval = krb5_get_init_creds_keytab(context, &creds, princ, NULL, 0, NULL, &options)))
|
||||
com_err(prog, retval, "while getting initial credentials");
|
||||
|
||||
if ((retval = krb5_cc_initialize(context, cache, princ)))
|
||||
|
@ -73,7 +74,6 @@ void ceo_krb5_auth(char *principal, char *ktname) {
|
|||
com_err(prog, retval, "while storing credentials");
|
||||
|
||||
krb5_free_cred_contents(context, &creds);
|
||||
krb5_kt_close(context, keytab);
|
||||
krb5_free_principal(context, princ);
|
||||
krb5_cc_close(context, cache);
|
||||
}
|
||||
|
@ -82,6 +82,8 @@ void ceo_krb5_deauth() {
|
|||
krb5_error_code retval;
|
||||
krb5_ccache cache;
|
||||
|
||||
debug("krb5: destroying credentials");
|
||||
|
||||
if ((retval = krb5_cc_default(context, &cache)))
|
||||
com_err(prog, retval, "while resolving credentials cache");
|
||||
|
||||
|
@ -90,6 +92,7 @@ void ceo_krb5_deauth() {
|
|||
}
|
||||
|
||||
void ceo_krb5_cleanup() {
|
||||
debug("krb5: cleaning up");
|
||||
krb5_free_context(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ extern krb5_context context;
|
|||
void ceo_krb5_init();
|
||||
void ceo_krb5_cleanup();
|
||||
|
||||
void ceo_krb5_auth(char *, char *);
|
||||
void ceo_krb5_auth(char *);
|
||||
void ceo_krb5_deauth();
|
||||
|
||||
int ceo_read_password(char *, unsigned int, int);
|
||||
|
|
34
src/ldap.c
34
src/ldap.c
|
@ -170,7 +170,7 @@ int ceo_add_group_sudo(char *group, char *basedn) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, char *shell, int no, ...) {
|
||||
int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, char *principal, char *shell, int no, ...) {
|
||||
va_list args;
|
||||
|
||||
if (!uid || !basedn || !cn || !home || !shell)
|
||||
|
@ -179,13 +179,19 @@ int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home,
|
|||
LDAPMod *mods[16];
|
||||
int i = -1;
|
||||
int ret = 0;
|
||||
int classes = 4;
|
||||
|
||||
mods[++i] = xmalloc(sizeof(LDAPMod));
|
||||
mods[i]->mod_op = LDAP_MOD_ADD;
|
||||
mods[i]->mod_type = "objectClass";
|
||||
char *objectClasses[] = { "top", "account", "posixAccount", "shadowAccount", NULL, NULL };
|
||||
char *objectClasses[] = { "top", "account", "posixAccount", "shadowAccount", NULL, NULL, NULL, NULL };
|
||||
if (objclass != NULL)
|
||||
objectClasses[4] = objclass;
|
||||
objectClasses[classes++] = objclass;
|
||||
if (principal) {
|
||||
objectClasses[classes++] = "krbPrincipalAux";
|
||||
objectClasses[classes++] = "krbTicketPolicyAux";
|
||||
|
||||
}
|
||||
mods[i]->mod_values = objectClasses;
|
||||
|
||||
mods[++i] = xmalloc(sizeof(LDAPMod));
|
||||
|
@ -225,6 +231,14 @@ int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home,
|
|||
char *homeDirectory[] = { home, NULL };
|
||||
mods[i]->mod_values = homeDirectory;
|
||||
|
||||
if (principal) {
|
||||
mods[++i] = xmalloc(sizeof(LDAPMod));
|
||||
mods[i]->mod_op = LDAP_MOD_ADD;
|
||||
mods[i]->mod_type = "krbPrincipalName";
|
||||
char *krbPrincipalName[] = { principal, NULL };
|
||||
mods[i]->mod_values = krbPrincipalName;
|
||||
}
|
||||
|
||||
va_start(args, no);
|
||||
char *attr;
|
||||
while ((attr = va_arg(args, char *))) {
|
||||
|
@ -277,7 +291,7 @@ int ceo_new_uid(int min, int max) {
|
|||
continue;
|
||||
|
||||
snprintf(filter, sizeof(filter), "(|(uidNumber=%d)(gidNumber=%d))", i, i);
|
||||
if (ldap_search_s(ld, users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 1, &res) != LDAP_SUCCESS) {
|
||||
if (ldap_search_s(ld, ldap_users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 1, &res) != LDAP_SUCCESS) {
|
||||
ldap_err("firstuid");
|
||||
return -1;
|
||||
}
|
||||
|
@ -306,7 +320,7 @@ int ceo_user_exists(char *uid) {
|
|||
|
||||
snprintf(filter, sizeof(filter), "uid=%s", uid);
|
||||
|
||||
if (ldap_search_s(ld, users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) {
|
||||
if (ldap_search_s(ld, ldap_users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) {
|
||||
ldap_err("user_exists");
|
||||
return -1;
|
||||
}
|
||||
|
@ -328,7 +342,7 @@ int ceo_group_exists(char *cn) {
|
|||
|
||||
snprintf(filter, sizeof(filter), "cn=%s", cn);
|
||||
|
||||
if (ldap_search_s(ld, groups_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) {
|
||||
if (ldap_search_s(ld, ldap_groups_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) {
|
||||
ldap_err("group_exists");
|
||||
return -1;
|
||||
}
|
||||
|
@ -362,22 +376,18 @@ void ceo_ldap_init() {
|
|||
int proto = LDAP_DEFAULT_PROTOCOL;
|
||||
const char *sasl_mech = "GSSAPI";
|
||||
|
||||
if (!admin_bind_userid || !admin_bind_keytab)
|
||||
if (!ldap_admin_principal)
|
||||
fatal("not configured");
|
||||
|
||||
if (ldap_initialize(&ld, server_url) != LDAP_SUCCESS)
|
||||
if (ldap_initialize(&ld, ldap_server_url) != LDAP_SUCCESS)
|
||||
ldap_fatal("ldap_initialize");
|
||||
|
||||
if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) != LDAP_OPT_SUCCESS)
|
||||
ldap_fatal("ldap_set_option");
|
||||
|
||||
ceo_krb5_auth(admin_bind_userid, admin_bind_keytab);
|
||||
|
||||
if (ldap_sasl_interactive_bind_s(ld, NULL, sasl_mech, NULL, NULL,
|
||||
LDAP_SASL_QUIET, &ldap_sasl_interact, NULL) != LDAP_SUCCESS)
|
||||
ldap_fatal("Bind failed");
|
||||
|
||||
ceo_krb5_deauth();
|
||||
}
|
||||
|
||||
void ceo_ldap_cleanup() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define LDAP_DEFAULT_PROTOCOL LDAP_VERSION3
|
||||
|
||||
int ceo_add_user(char *, char *, char *, char *, char *, char *, int, ...);
|
||||
int ceo_add_user(char *, char *, char *, char *, char *, char *, char *, int, ...);
|
||||
int ceo_add_group(char *, char *, int);
|
||||
int ceo_add_group_sudo(char *, char *);
|
||||
int ceo_new_uid(int, int);
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "net.h"
|
||||
#include "gss.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
struct strbuf fqdn = STRBUF_INIT;
|
||||
|
||||
const size_t MAX_MSGLEN = 65536;
|
||||
const size_t MSG_BUFINC = 4096;
|
||||
|
||||
void setup_fqdn(void) {
|
||||
struct utsname uts;
|
||||
struct hostent *lo;
|
||||
|
||||
if (uname(&uts))
|
||||
fatalpe("uname");
|
||||
lo = gethostbyname(uts.nodename);
|
||||
if (!lo)
|
||||
fatalpe("gethostbyname");
|
||||
|
||||
strbuf_addstr(&fqdn, lo->h_name);
|
||||
}
|
||||
|
||||
void free_fqdn(void) {
|
||||
strbuf_release(&fqdn);
|
||||
}
|
||||
|
||||
static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) {
|
||||
size_t len = 0;
|
||||
int flags = 0;
|
||||
int bytes;
|
||||
|
||||
strbuf_reset(msg);
|
||||
|
||||
do {
|
||||
msg_meta->fromlen = sizeof(msg_meta->from);
|
||||
|
||||
bytes = sctp_recvmsg(sock, msg->buf + len, strbuf_avail(msg) - len,
|
||||
(sa *)&msg_meta->from, &msg_meta->fromlen, &msg_meta->sinfo, &flags);
|
||||
|
||||
if (bytes < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
fatalpe("sctp_recvmsg");
|
||||
}
|
||||
if (!bytes)
|
||||
break;
|
||||
len += bytes;
|
||||
|
||||
if (msg->len > MAX_MSGLEN)
|
||||
fatal("oversized message received");
|
||||
if (strbuf_avail(msg) < MSG_BUFINC)
|
||||
strbuf_grow(msg, MSG_BUFINC);
|
||||
|
||||
} while (~flags & MSG_EOR);
|
||||
|
||||
if (!bytes && len)
|
||||
fatalpe("EOF in the middle of a message");
|
||||
|
||||
*notification = flags & MSG_NOTIFICATION;
|
||||
if (*notification) {
|
||||
notification_dbg(msg->buf);
|
||||
union sctp_notification *sn = (union sctp_notification *) msg->buf;
|
||||
switch (sn->sn_header.sn_type) {
|
||||
case SCTP_SHUTDOWN_EVENT:
|
||||
fatal("connection shut down");
|
||||
break;
|
||||
case SCTP_ASSOC_CHANGE:
|
||||
switch (sn->sn_assoc_change.sac_state) {
|
||||
case SCTP_COMM_LOST:
|
||||
fatal("connection lost");
|
||||
break;
|
||||
case SCTP_SHUTDOWN_COMP:
|
||||
fatal("shutdown complete");
|
||||
break;
|
||||
case SCTP_CANT_STR_ASSOC:
|
||||
fatal("connection failed (is ceod running?)");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strbuf_setlen(msg, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg) {
|
||||
int notification = 0;
|
||||
|
||||
do {
|
||||
recv_one_message(sock, msg_meta, msg, ¬ification);
|
||||
} while (notification);
|
||||
|
||||
return msg->len > 0;
|
||||
}
|
||||
|
||||
void notification_dbg(char *notification) {
|
||||
union sctp_notification *sn = (union sctp_notification *) notification;
|
||||
char *extra;
|
||||
|
||||
switch (sn->sn_header.sn_type) {
|
||||
case SCTP_ASSOC_CHANGE:
|
||||
extra = "unknown state";
|
||||
switch (sn->sn_assoc_change.sac_state) {
|
||||
case SCTP_COMM_UP: extra = "established"; break;
|
||||
case SCTP_COMM_LOST: extra = "lost"; break;
|
||||
case SCTP_RESTART: extra = "restarted"; break;
|
||||
case SCTP_SHUTDOWN_COMP: extra = "completed shutdown"; break;
|
||||
case SCTP_CANT_STR_ASSOC: extra = "cannot start"; break;
|
||||
}
|
||||
debug("association changed: association 0x%x %s", sn->sn_assoc_change.sac_assoc_id, extra);
|
||||
break;
|
||||
case SCTP_PEER_ADDR_CHANGE:
|
||||
extra = "unknown state";
|
||||
switch (sn->sn_paddr_change.spc_state) {
|
||||
case SCTP_ADDR_AVAILABLE: extra = "unavailable"; break;
|
||||
case SCTP_ADDR_UNREACHABLE: extra = "unreachable"; break;
|
||||
case SCTP_ADDR_REMOVED: extra = "removed"; break;
|
||||
case SCTP_ADDR_ADDED: extra = "added"; break;
|
||||
case SCTP_ADDR_MADE_PRIM: extra = "made primary"; break;
|
||||
#ifdef SCTP_ADDR_CONFIRMED
|
||||
case SCTP_ADDR_CONFIRMED: extra = "confirmed"; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *) &sn->sn_paddr_change.spc_aaddr;
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &sa->sin_addr, addr, sizeof(addr));
|
||||
debug("peer address change: remote address %s %s", addr, extra);
|
||||
break;
|
||||
case SCTP_REMOTE_ERROR:
|
||||
debug("remote error: association=0x%x error=0x%x",
|
||||
sn->sn_remote_error.sre_assoc_id,
|
||||
sn->sn_remote_error.sre_error);
|
||||
break;
|
||||
case SCTP_SEND_FAILED:
|
||||
debug("send failed: association=0x%x error=0x%x",
|
||||
sn->sn_send_failed.ssf_assoc_id,
|
||||
sn->sn_send_failed.ssf_error);
|
||||
break;
|
||||
case SCTP_ADAPTATION_INDICATION:
|
||||
debug("adaptation indication: 0x%x",
|
||||
sn->sn_adaptation_event.sai_adaptation_ind);
|
||||
break;
|
||||
case SCTP_PARTIAL_DELIVERY_EVENT:
|
||||
extra = "unknown indication";
|
||||
switch (sn->sn_pdapi_event.pdapi_indication) {
|
||||
case SCTP_PARTIAL_DELIVERY_ABORTED:
|
||||
extra = "partial delivery aborted";
|
||||
break;
|
||||
}
|
||||
debug("partial delivery event: %s", extra);
|
||||
break;
|
||||
case SCTP_SHUTDOWN_EVENT:
|
||||
debug("association 0x%x was shut down",
|
||||
sn->sn_shutdown_event.sse_assoc_id);
|
||||
break;
|
||||
default:
|
||||
debug("unknown sctp notification type 0x%x\n",
|
||||
sn->sn_header.sn_type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/sctp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <gssapi/gssapi.h>
|
||||
|
||||
#if ! defined(SCTP_ADDR_CONFIRMED) && defined(__linux__)
|
||||
#define SCTP_ADDR_CONFIRMED 5
|
||||
#endif
|
||||
|
||||
void notification_dbg(char *);
|
||||
|
||||
#ifdef SCTP_ADAPTION_LAYER
|
||||
#define sctp_adaptation_layer_event sctp_adaption_layer_event
|
||||
#define sn_adaptation_event sn_adaption_event
|
||||
#define sai_adaptation_ind sai_adaption_ind
|
||||
#define SCTP_ADAPTATION_INDICATION SCTP_ADAPTION_INDICATION
|
||||
#endif
|
||||
|
||||
typedef struct sockaddr sa;
|
||||
|
||||
extern struct strbuf fqdn;
|
||||
extern void setup_fqdn(void);
|
||||
extern void free_fqdn(void);
|
||||
|
||||
struct sctp_meta {
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen;
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
};
|
||||
|
||||
enum {
|
||||
MSG_AUTH = 0x8000000,
|
||||
MSG_EXPLODE = 0x8000001,
|
||||
};
|
||||
|
||||
#ifdef MSG_ABORT
|
||||
#define SCTP_ABORT MSG_ABORT
|
||||
#define SCTP_EOF MSG_EOF
|
||||
#endif
|
||||
|
||||
#define EKERB -2
|
||||
#define ELDAP -3
|
||||
#define EHOME -4
|
||||
|
||||
int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg);
|
|
@ -0,0 +1,305 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <alloca.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "net.h"
|
||||
#include "ceo.pb-c.h"
|
||||
#include "config.h"
|
||||
#include "gss.h"
|
||||
#include "krb5.h"
|
||||
#include "ldap.h"
|
||||
#include "homedir.h"
|
||||
#include "kadm.h"
|
||||
#include "daemon.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
char *prog;
|
||||
|
||||
static const int MAX_MESSAGES = 32;
|
||||
static const int MAX_MESGSIZE = 512;
|
||||
|
||||
char *user_types[] = {
|
||||
[CEO__ADD_USER__TYPE__MEMBER] = "member",
|
||||
[CEO__ADD_USER__TYPE__CLUB] = "club",
|
||||
};
|
||||
|
||||
Ceo__AddUserResponse *response_create(void) {
|
||||
Ceo__AddUserResponse *r = xmalloc(sizeof(Ceo__AddUserResponse));
|
||||
ceo__add_user_response__init(r);
|
||||
r->n_messages = 0;
|
||||
r->messages = xmalloc(MAX_MESSAGES * sizeof(Ceo__StatusMessage *));
|
||||
return r;
|
||||
}
|
||||
|
||||
int32_t response_message(Ceo__AddUserResponse *r, int32_t status, char *fmt, ...) {
|
||||
va_list args;
|
||||
Ceo__StatusMessage *statusmsg = xmalloc(sizeof(Ceo__StatusMessage));
|
||||
char *message = xmalloc(MAX_MESGSIZE);
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(message, MAX_MESGSIZE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
ceo__status_message__init(statusmsg);
|
||||
statusmsg->status = status;
|
||||
statusmsg->message = message;
|
||||
|
||||
if (r->n_messages >= MAX_MESSAGES)
|
||||
fatal("too many messages");
|
||||
r->messages[r->n_messages++] = statusmsg;
|
||||
|
||||
if (status)
|
||||
error("%s", message);
|
||||
else
|
||||
notice("%s", message);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void response_delete(Ceo__AddUserResponse *r) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < r->n_messages; i++) {
|
||||
free(r->messages[i]->message);
|
||||
free(r->messages[i]);
|
||||
}
|
||||
free(r->messages);
|
||||
free(r);
|
||||
}
|
||||
|
||||
|
||||
static int check_adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) {
|
||||
int office = check_group(client, "office");
|
||||
int syscom = check_group(client, "syscom");
|
||||
|
||||
notice("adding uid=%s cn=%s by %s", in->username, in->realname, client);
|
||||
|
||||
if (!office && !syscom)
|
||||
return response_message(out, EPERM, "%s not authorized to create users", client);
|
||||
|
||||
if (!in->username)
|
||||
return response_message(out, EINVAL, "missing required argument: username");
|
||||
if (!in->realname)
|
||||
return response_message(out, EINVAL, "missing required argument: realname");
|
||||
|
||||
if (in->type == CEO__ADD_USER__TYPE__MEMBER) {
|
||||
if (!in->password)
|
||||
return response_message(out, EINVAL, "missing required argument: password");
|
||||
} else if (in->type == CEO__ADD_USER__TYPE__CLUB) {
|
||||
if (in->password)
|
||||
return response_message(out, EINVAL, "club accounts cannot have passwords");
|
||||
if (in->program)
|
||||
return response_message(out, EINVAL, "club accounts cannot have programs");
|
||||
} else {
|
||||
return response_message(out, EINVAL, "invalid user type: %d", in->type);
|
||||
}
|
||||
|
||||
if (getpwnam(in->username) != NULL)
|
||||
return response_message(out, EEXIST, "user %s already exists", in->username);
|
||||
|
||||
if (getgrnam(in->username) != NULL)
|
||||
return response_message(out, EEXIST, "group %s already exists", in->username);
|
||||
|
||||
if (ceo_user_exists(in->username))
|
||||
return response_message(out, EEXIST, "user %s already exists in LDAP", in->username);
|
||||
|
||||
if (ceo_group_exists(in->username))
|
||||
return response_message(out, EEXIST, "group %s already exists in LDAP", in->username);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adduser_spam(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client, char *prog, int status) {
|
||||
char *argv[] = {
|
||||
notify_hook, prog, client,
|
||||
in->username, in->realname, in->program ?: "",
|
||||
status ? "failure" : "success", NULL
|
||||
};
|
||||
|
||||
struct strbuf message = STRBUF_INIT;
|
||||
for (int i = 0; i < out->n_messages; i++)
|
||||
strbuf_addf(&message, "%s\n", out->messages[i]->message);
|
||||
|
||||
spawnv_msg(notify_hook, argv, &message);
|
||||
strbuf_release(&message);
|
||||
}
|
||||
|
||||
static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) {
|
||||
char homedir[1024];
|
||||
char principal[1024];
|
||||
int user_stat, group_stat, krb_stat, home_stat;
|
||||
int id;
|
||||
|
||||
if (snprintf(principal, sizeof(principal), "%s@%s",
|
||||
in->username, krb5_realm) >= sizeof(principal))
|
||||
fatal("principal overflow");
|
||||
|
||||
if (snprintf(homedir, sizeof(homedir), "%s/%s",
|
||||
member_home, in->username) >= sizeof(homedir))
|
||||
fatal("homedir overflow");
|
||||
|
||||
if ((id = ceo_new_uid(member_min_id, member_max_id)) <= 0)
|
||||
fatal("no available uids in range [%ld, %ld]", member_min_id, member_max_id);
|
||||
|
||||
if ((krb_stat = ceo_del_princ(in->username)))
|
||||
return response_message(out, EEXIST, "unable to overwrite orphaned kerberos principal %s", in->username);
|
||||
|
||||
if ((user_stat = ceo_add_user(in->username, ldap_users_base, "member", in->realname, homedir, principal,
|
||||
member_shell, id, "program", in->program, NULL)))
|
||||
return response_message(out, ELDAP, "unable to create ldap account %s", in->username);
|
||||
response_message(out, 0, "successfully created ldap account");
|
||||
|
||||
/* errors that occur after this point are not fatal */
|
||||
|
||||
if ((krb_stat = ceo_add_princ(in->username, in->password)))
|
||||
return response_message(out, EKERB, "unable to create kerberos principal %s", in->username);
|
||||
response_message(out, 0, "successfully created principal");
|
||||
|
||||
if ((group_stat = ceo_add_group(in->username, ldap_groups_base, id)))
|
||||
response_message(out, ELDAP, "unable to create ldap group %s", in->username);
|
||||
else
|
||||
response_message(out, 0, "successfully created ldap group");
|
||||
|
||||
if ((home_stat = ceo_create_home(homedir, member_home_skel, id, id)))
|
||||
response_message(out, EHOME, "unable to create home directory for %s", in->username);
|
||||
else
|
||||
response_message(out, 0, "successfully created home directory");
|
||||
|
||||
|
||||
return krb_stat || user_stat || group_stat || home_stat;
|
||||
}
|
||||
|
||||
static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) {
|
||||
char homedir[1024];
|
||||
int krb_stat, user_stat, group_stat, sudo_stat, home_stat;
|
||||
int id;
|
||||
|
||||
if (snprintf(homedir, sizeof(homedir), "%s/%s",
|
||||
club_home, in->username) >= sizeof(homedir))
|
||||
fatal("homedir overflow");
|
||||
|
||||
if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0)
|
||||
fatal("no available uids in range [%ld, %ld]", club_min_id, club_max_id);
|
||||
|
||||
if ((krb_stat = ceo_del_princ(in->username)))
|
||||
return response_message(out, EKERB, "unable to clear principal %s", in->username);
|
||||
|
||||
if ((user_stat = ceo_add_user(in->username, ldap_users_base, "club", in->realname, homedir,
|
||||
NULL, club_shell, id, NULL)))
|
||||
return response_message(out, ELDAP, "unable to create ldap account %s", in->username);
|
||||
response_message(out, 0, "successfully created ldap account");
|
||||
|
||||
/* errors that occur after this point are not fatal */
|
||||
|
||||
if ((group_stat = ceo_add_group(in->username, ldap_groups_base, id)))
|
||||
response_message(out, ELDAP, "unable to create ldap group %s", in->username);
|
||||
else
|
||||
response_message(out, 0, "successfully created ldap group");
|
||||
|
||||
if ((sudo_stat = ceo_add_group_sudo(in->username, ldap_sudo_base)))
|
||||
response_message(out, ELDAP, "unable to create ldap sudoers %s", in->username);
|
||||
else
|
||||
response_message(out, 0, "successfully created ldap sudoers");
|
||||
|
||||
if ((home_stat = ceo_create_home(homedir, club_home_skel, id, id)))
|
||||
response_message(out, EHOME, "unable to create home directory for %s", in->username);
|
||||
else
|
||||
response_message(out, 0, "successfully created home directory");
|
||||
|
||||
return user_stat || group_stat || sudo_stat || home_stat;
|
||||
}
|
||||
|
||||
static int32_t adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) {
|
||||
int32_t chk_stat, status;
|
||||
char *prog;
|
||||
|
||||
chk_stat = check_adduser(in, out, client);
|
||||
if (chk_stat)
|
||||
return chk_stat;
|
||||
|
||||
if (in->type == CEO__ADD_USER__TYPE__MEMBER) {
|
||||
status = addmember(in, out);
|
||||
prog = "addmember";
|
||||
} else if (in->type == CEO__ADD_USER__TYPE__CLUB) {
|
||||
status = addclub(in, out);
|
||||
prog = "addclub";
|
||||
} else {
|
||||
fatal("unknown user type %d", in->type);
|
||||
}
|
||||
|
||||
if (status)
|
||||
response_message(out, 0, "there were failures, please contact systems committee");
|
||||
|
||||
adduser_spam(in, out, client, prog, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void cmd_adduser(void) {
|
||||
Ceo__AddUser *in_proto;
|
||||
Ceo__AddUserResponse *out_proto = response_create();
|
||||
struct strbuf in = STRBUF_INIT;
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
|
||||
if (strbuf_read(&in, STDIN_FILENO, 0) < 0)
|
||||
fatalpe("read");
|
||||
|
||||
in_proto = ceo__add_user__unpack(&protobuf_c_default_allocator,
|
||||
in.len, (uint8_t *)in.buf);
|
||||
if (!in_proto)
|
||||
fatal("malformed add user message");
|
||||
|
||||
char *client = getenv("CEO_USER");
|
||||
if (!client)
|
||||
fatal("environment variable CEO_USER is not set");
|
||||
|
||||
adduser(in_proto, out_proto, client);
|
||||
|
||||
strbuf_grow(&out, ceo__add_user_response__get_packed_size(out_proto));
|
||||
strbuf_setlen(&out, ceo__add_user_response__pack(out_proto, (uint8_t *)out.buf));
|
||||
full_write(STDOUT_FILENO, out.buf, out.len);
|
||||
|
||||
ceo__add_user__free_unpacked(in_proto, &protobuf_c_default_allocator);
|
||||
response_delete(out_proto);
|
||||
|
||||
strbuf_release(&in);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
prog = xstrdup(basename(argv[0]));
|
||||
init_log(prog, LOG_PID, LOG_AUTHPRIV);
|
||||
|
||||
configure();
|
||||
|
||||
if (setenv("KRB5CCNAME", "MEMORY:adduser", 1))
|
||||
fatalpe("setenv");
|
||||
|
||||
ceo_krb5_init();
|
||||
ceo_krb5_auth(ldap_admin_principal);
|
||||
ceo_ldap_init();
|
||||
ceo_kadm_init();
|
||||
|
||||
cmd_adduser();
|
||||
|
||||
ceo_kadm_cleanup();
|
||||
ceo_ldap_cleanup();
|
||||
ceo_krb5_deauth();
|
||||
ceo_krb5_cleanup();
|
||||
|
||||
free_config();
|
||||
free(prog);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "strbuf.h"
|
||||
#include "ops.h"
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
|
||||
static struct op *ops;
|
||||
|
||||
static const char *default_op_dir = "/usr/lib/ceod";
|
||||
static const char *op_dir;
|
||||
|
||||
static void add_op(char *host, char *name, uint32_t id) {
|
||||
struct op *new = xmalloc(sizeof(struct op));
|
||||
errno = 0;
|
||||
new->next = ops;
|
||||
new->name = xstrdup(name);
|
||||
new->id = id;
|
||||
new->path = NULL;
|
||||
|
||||
struct hostent *hostent = gethostbyname(host);
|
||||
if (!hostent)
|
||||
badconf("cannot add op %s: %s: %s", name, host, hstrerror(h_errno));
|
||||
new->hostname = strdup(hostent->h_name);
|
||||
new->local = !strcmp(fqdn.buf, hostent->h_name);
|
||||
new->addr = *(struct in_addr *)hostent->h_addr_list[0];
|
||||
|
||||
if (new->local) {
|
||||
new->path = xmalloc(strlen(op_dir) + strlen("/op-") + strlen(name) + 1);
|
||||
sprintf(new->path, "%s/op-%s", op_dir, name);
|
||||
if (access(new->path, X_OK))
|
||||
fatalpe("cannot add op: %s: %s", name, new->path);
|
||||
}
|
||||
|
||||
ops = new;
|
||||
debug("added op %s (%s%s)", new->name, new->local ? "" : "on ",
|
||||
new->local ? "local" : host);
|
||||
}
|
||||
|
||||
struct op *get_local_op(uint32_t id) {
|
||||
for (struct op *op = ops; op; op = op->next) {
|
||||
if (op->local && op->id == id)
|
||||
return op;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct op *find_op(const char *name) {
|
||||
for (struct op *op = ops; op; op = op->next) {
|
||||
if (!strcmp(name, op->name))
|
||||
return op;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void setup_ops(void) {
|
||||
char op_config_dir[1024];
|
||||
DIR *dp;
|
||||
struct dirent *de;
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
unsigned lineno = 0;
|
||||
unsigned op_count = 0;
|
||||
|
||||
op_dir = getenv("CEO_LIB_DIR") ?: default_op_dir;
|
||||
|
||||
if (snprintf(op_config_dir, sizeof(op_config_dir), "%s/%s", config_dir, "ops") >= sizeof(op_config_dir))
|
||||
fatal("ops dir path too long");
|
||||
|
||||
dp = opendir(op_config_dir);
|
||||
if (!dp)
|
||||
fatalpe("opendir: %s", op_config_dir);
|
||||
|
||||
while ((de = readdir(dp))) {
|
||||
FILE *fp = fopenat(dp, de->d_name, O_RDONLY);
|
||||
if (!fp)
|
||||
warnpe("open: %s/%s", op_config_dir, de->d_name);
|
||||
while (strbuf_getline(&line, fp, '\n') != EOF) {
|
||||
lineno++;
|
||||
strbuf_trim(&line);
|
||||
|
||||
if (!line.len || line.buf[0] == '#')
|
||||
continue;
|
||||
|
||||
struct strbuf **words = strbuf_splitws(&line);
|
||||
|
||||
if (strbuf_list_len(words) != 3)
|
||||
badconf("%s/%s: expected three words on line %d", op_config_dir, de->d_name, lineno);
|
||||
|
||||
errno = 0;
|
||||
char *end;
|
||||
int id = strtol(words[2]->buf, &end, 0);
|
||||
if (errno || *end)
|
||||
badconf("%s/%s: invalid id '%s' on line %d", op_config_dir, de->d_name, words[2]->buf, lineno);
|
||||
|
||||
add_op(words[0]->buf, words[1]->buf, id);
|
||||
op_count++;
|
||||
|
||||
strbuf_list_free(words);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
strbuf_release(&line);
|
||||
}
|
||||
|
||||
void free_ops(void) {
|
||||
while (ops) {
|
||||
struct op *next = ops->next;
|
||||
free(ops->name);
|
||||
free(ops->hostname);
|
||||
free(ops->path);
|
||||
free(ops);
|
||||
ops = next;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
struct op {
|
||||
char *name;
|
||||
uint32_t id;
|
||||
int local;
|
||||
char *hostname;
|
||||
char *path;
|
||||
struct in_addr addr;
|
||||
struct op *next;
|
||||
};
|
||||
|
||||
void setup_ops(void);
|
||||
void free_ops(void);
|
||||
struct op *find_op(const char *name);
|
||||
struct op *get_local_op(uint32_t id);
|
|
@ -53,7 +53,7 @@ static void parse_name(struct config_file *file, char *name, size_t maxlen) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!isalpha(c) && c != '_' && c != '-') {
|
||||
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') {
|
||||
unparse_char(file, c);
|
||||
break;
|
||||
}
|
||||
|
|
131
src/util.c
131
src/util.c
|
@ -1,10 +1,13 @@
|
|||
#define _ATFILE_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "strbuf.h"
|
||||
|
@ -26,6 +29,8 @@ static void errmsg(int prio, const char *prefix, const char *fmt, va_list args)
|
|||
syslog(prio, "%s", msg.buf);
|
||||
if (log_stderr)
|
||||
fputs(msg.buf, stderr);
|
||||
|
||||
strbuf_release(&msg);
|
||||
}
|
||||
|
||||
static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) {
|
||||
|
@ -38,6 +43,8 @@ static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args
|
|||
syslog(prio, "%s", msg.buf);
|
||||
if (log_stderr)
|
||||
fputs(msg.buf, stderr);
|
||||
|
||||
strbuf_release(&msg);
|
||||
}
|
||||
|
||||
NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) {
|
||||
|
@ -148,3 +155,127 @@ int spawnv(const char *path, char *const argv[]) {
|
|||
exit(execv(path, argv));
|
||||
return status;
|
||||
}
|
||||
|
||||
void full_write(int fd, const void *buf, size_t count) {
|
||||
ssize_t total = 0;
|
||||
|
||||
while (total < count) {
|
||||
ssize_t wcount = write(fd, (char *)buf + total, count - total);
|
||||
if (wcount < 0)
|
||||
fatalpe("write");
|
||||
total += wcount;
|
||||
}
|
||||
}
|
||||
|
||||
int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr) {
|
||||
int pid, wpid, status;
|
||||
int tochild[2];
|
||||
int fmchild[2];
|
||||
|
||||
if (pipe(tochild))
|
||||
fatalpe("pipe");
|
||||
if (pipe(fmchild))
|
||||
fatalpe("pipe");
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
fatalpe("fork");
|
||||
if (!pid) {
|
||||
dup2(tochild[0], STDIN_FILENO);
|
||||
dup2(fmchild[1], STDOUT_FILENO);
|
||||
if (cap_stderr)
|
||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||
close(tochild[0]);
|
||||
close(tochild[1]);
|
||||
close(fmchild[0]);
|
||||
close(fmchild[1]);
|
||||
execve(path, argv, envp);
|
||||
fatalpe("execve");
|
||||
} else {
|
||||
close(tochild[0]);
|
||||
close(fmchild[1]);
|
||||
full_write(tochild[1], output->buf, output->len);
|
||||
close(tochild[1]);
|
||||
|
||||
if (input)
|
||||
strbuf_read(input, fmchild[0], 0);
|
||||
close(fmchild[0]);
|
||||
}
|
||||
|
||||
wpid = waitpid(pid, &status, 0);
|
||||
if (wpid < 0)
|
||||
fatalpe("waitpid");
|
||||
else if (wpid != pid)
|
||||
fatal("waitpid is broken");
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status))
|
||||
notice("child %s exited with status %d", path, WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
notice("child %s killed by signal %d", path, WTERMSIG(status));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output) {
|
||||
return spawnvem(path, argv, environ, output, NULL, 0);
|
||||
}
|
||||
|
||||
int check_group(char *username, char *group) {
|
||||
struct group *grp = getgrnam(group);
|
||||
char **members;
|
||||
|
||||
if (grp)
|
||||
for (members = grp->gr_mem; *members; members++)
|
||||
if (!strcmp(username, *members))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fopenat(DIR *d, const char *path, int flags) {
|
||||
int dfd = dirfd(d);
|
||||
if (dfd < 0)
|
||||
return NULL;
|
||||
int fd = openat(dfd, path, flags);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return fdopen(fd, flags & O_RDWR ? "r+" :
|
||||
flags & O_WRONLY ? "w" :
|
||||
"r");
|
||||
}
|
||||
|
||||
void make_env(char **envp, ...) {
|
||||
const size_t len = 4096;
|
||||
size_t used = 0;
|
||||
int args = 0;
|
||||
char *buf = xmalloc(len);
|
||||
va_list ap;
|
||||
va_start(ap, envp);
|
||||
char *name, *val;
|
||||
|
||||
while ((name = va_arg(ap, char *))) {
|
||||
val = va_arg(ap, char *);
|
||||
if (!val)
|
||||
continue;
|
||||
int n = snprintf(buf + used, len - used, "%s=%s", name, val);
|
||||
if (n < 0)
|
||||
fatalpe("snprintf");
|
||||
if (n >= len - used)
|
||||
fatal("environment too big");
|
||||
|
||||
envp[args++] = buf + used;
|
||||
used += n + 1;
|
||||
}
|
||||
|
||||
if (!args)
|
||||
free(buf);
|
||||
|
||||
envp[args] = NULL;
|
||||
}
|
||||
|
||||
void free_env(char **envp) {
|
||||
free(*envp);
|
||||
}
|
||||
|
|
17
src/util.h
17
src/util.h
|
@ -2,8 +2,14 @@
|
|||
#define CEO_UTIL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "strbuf.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
|
@ -17,8 +23,18 @@
|
|||
#define LOG_AUTHPRIV LOG_AUTH
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int spawnv(const char *path, char *const *argv);
|
||||
int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output);
|
||||
int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr);
|
||||
void full_write(int fd, const void *buf, size_t count);
|
||||
ssize_t full_read(int fd, void *buf, size_t len);
|
||||
FILE *fopenat(DIR *d, const char *path, int flags);
|
||||
void make_env(char **envp, ...);
|
||||
void free_env(char **envp);
|
||||
void init_log(const char *ident, int option, int facility);
|
||||
int check_group(char *username, char *group);
|
||||
|
||||
PRINTF_LIKE(0) NORETURN void fatal(const char *, ...);
|
||||
PRINTF_LIKE(0) NORETURN void fatalpe(const char *, ...);
|
||||
|
@ -59,7 +75,6 @@ static inline void *xcalloc(size_t nmemb, size_t size) {
|
|||
return alloc;
|
||||
}
|
||||
|
||||
|
||||
static inline char *xstrdup(const char *s) {
|
||||
char *dup = strdup(s);
|
||||
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 7) {
|
||||
fprintf(stderr, "Usage: zfsaddhomedir homedir refquota skeldir uid gid mode acl\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *homedir = argv[1];
|
||||
char *skeldir = argv[3];
|
||||
char refquota[32];
|
||||
char *mode = argv[6];
|
||||
char *acl = (argc >= 8) ? argv[7] : NULL;
|
||||
uid_t uid, gid;
|
||||
char *zfs_bin = "/usr/sbin/zfs";
|
||||
char *chmod_bin = "/usr/bin/chmod";
|
||||
char *dataset = homedir + 1;
|
||||
char *create_argv[] = { "zfs", "create", dataset, NULL };
|
||||
char *quota_argv[] = { "zfs", "set", refquota, dataset, NULL };
|
||||
char *mode_argv[] = { "chmod", mode, homedir, NULL };
|
||||
char *acl_argv[] = { "chmod", acl, homedir, NULL };
|
||||
DIR *skel;
|
||||
struct dirent *skelent;
|
||||
|
||||
assert(homedir[0]);
|
||||
uid = atol(argv[4]);
|
||||
gid = atol(argv[5]);
|
||||
snprintf(refquota, sizeof(refquota), "refquota=%s", argv[2]);
|
||||
|
||||
if(spawnv(zfs_bin, create_argv))
|
||||
return 1;
|
||||
if(spawnv(zfs_bin, quota_argv))
|
||||
return 1;
|
||||
if(spawnv(chmod_bin, mode_argv))
|
||||
return 1;
|
||||
if(acl && spawnv(chmod_bin, acl_argv))
|
||||
return 1;
|
||||
|
||||
skel = opendir(skeldir);
|
||||
if (!skel) {
|
||||
errorpe("failed to open %s", skeldir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((skelent = readdir(skel))) {
|
||||
struct stat sb;
|
||||
char src[PATH_MAX], dest[PATH_MAX];
|
||||
|
||||
if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, ".."))
|
||||
continue;
|
||||
|
||||
snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name);
|
||||
snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name);
|
||||
lstat(src, &sb);
|
||||
|
||||
if (sb.st_uid || sb.st_gid) {
|
||||
warn("not creating %s due to ownership", dest);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
int bytes;
|
||||
char buf[4096];
|
||||
|
||||
int srcfd = open(src, O_RDONLY);
|
||||
if (srcfd == -1) {
|
||||
warnpe("open: %s", src);
|
||||
continue;
|
||||
}
|
||||
|
||||
int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777);
|
||||
if (destfd == -1) {
|
||||
warnpe("open: %s", dest);
|
||||
close(srcfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
bytes = read(srcfd, buf, sizeof(buf));
|
||||
if (!bytes)
|
||||
break;
|
||||
if (bytes < 0) {
|
||||
warnpe("read");
|
||||
break;
|
||||
}
|
||||
if (write(destfd, buf, bytes) < 0) {
|
||||
warnpe("write");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fchown(destfd, uid, gid))
|
||||
errorpe("chown: %s", dest);
|
||||
|
||||
close(srcfd);
|
||||
close(destfd);
|
||||
} else if (S_ISDIR(sb.st_mode)) {
|
||||
if (mkdir(dest, sb.st_mode & 0777)) {
|
||||
warnpe("mkdir: %s", dest);
|
||||
continue;
|
||||
}
|
||||
if (chown(dest, uid, gid))
|
||||
errorpe("chown: %s", dest);
|
||||
} else if (S_ISLNK(sb.st_mode)) {
|
||||
char lnkdest[PATH_MAX];
|
||||
int bytes;
|
||||
bytes = readlink(src, lnkdest, sizeof(lnkdest));
|
||||
lnkdest[bytes] = '\0';
|
||||
if (bytes == -1) {
|
||||
warnpe("readlink: %s", src);
|
||||
continue;
|
||||
}
|
||||
if (symlink(lnkdest, dest)) {
|
||||
warnpe("symlink: %s", dest);
|
||||
continue;
|
||||
}
|
||||
if (lchown(dest, uid, gid))
|
||||
errorpe("lchown: %s", dest);
|
||||
} else {
|
||||
warn("not creating %s", dest);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(skel);
|
||||
|
||||
if (chown(homedir, uid, gid)) {
|
||||
errorpe("failed to chown %s", homedir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue