LIBLTDL = @LIBLTDL@
INCLTDL = @INCLTDL@
LTDL_SUBDIRS = @LTDL_SUBDIRS@
+CFLAGS += $(INCLTDL)
USE_SHARED_LIBS = @USE_SHARED_LIBS@
USE_STATIC_LIBS = @USE_STATIC_LIBS@
include Make.inc
MFLAGS += --no-print-directory
+# Speed up the build for developers. This means editing Make.inc,
+# and adding "BOILER = yes" to the bottom. Once that's done, the
+#
+#
+ifeq "$(BOILER)" "yes"
+
+# Require at least GNU Make 3.81 for the new build system
+# Don't allow 3.80. Allow any 3.8x. This will need to be changed
+# in a decade or two when GNU Make 3.90 is released.
+BOILERMAKE=$(subst 3.8,yes,$(subst 3.80,,$(MAKE_VERSION)))
+
+# The version of GNU Make is too old, don't use it.
+ifeq "" "$(findstring yes,$(BOILERMAKE))"
+BOILERMAKE=
+endif
+
+# Static-only builds still require libtool.
+# This is because it does all kinds of preload magic in order
+# to force the linker to put the libraries into the main binary.
+# We don't support that yet, so we miss it...
+ifneq "$(USE_SHARED_LIBS)" "yes"
+BOILERMAKE=
+endif
+endif
+
+# If possible, drastically decrease the build time.
+# The new build system means that
+ifneq "" "$(BOILERMAKE)"
+
+# Don't use libtool or libltdl.
+# They are a blight upon the face of the earth.
+LIBLTDL :=
+INCLTDL := -DWITH_DLOPEN
+CFLAGS += -DWITHOUT_LIBLTDL
+LIBTOOL := JLIBTOOL
+LTDL_SUBDIRS :=
+
+export DESTDIR := $(R)
+
+# And over-ride all of the other magic.
+include scripts/boiler.mk
+
+else
.PHONY: all clean install
SUBDIRS = $(LTDL_SUBDIRS) $(wildcard src raddb scripts doc)
clean:
@$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
@rm -f *~
+endif
.PHONY: tests
tests:
# we make sure DESTDIR is defined.
#
export DESTDIR := $(R)
+ifeq "$(BOILERMAKE)" ""
install:
$(INSTALL) -d -m 755 $(R)$(sbindir)
$(INSTALL) -d -m 755 $(R)$(bindir)
$(INSTALL) -m 644 $$i $(R)$(dictdir); \
done
$(LIBTOOL) --finish $(R)$(libdir)
+endif
ifneq ($(RADMIN),)
ifneq ($(RGROUP),)
--with-ascend-binary Include support for Ascend binary filter attributes (default=yes)
--with-threads Use threads, if available. (default=yes)
--with-vmps Compile in VMPS support. (default=yes)
- --with-dhcp Compile in DHCP support. (default=no)
+ --with-dhcp Compile in DHCP support. (default=yes)
--with-static-modules=QUOTED-MODULE-LIST
--with-modules=QUOTED-MODULE-LIST
--with-experimental-modules Use experimental and unstable modules. (default=no)
fi
+WITH_DHCP=yes
# Check whether --with-dhcp was given.
if test "${with_dhcp+set}" = set; then
withval=$with_dhcp; case "$withval" in
yes)
+ ;;
+ *)
+ WITH_DHCP=no
+ esac
+
+fi
+
+if test "x$WITH_DHCP" = "xyes"; then
cat >>confdefs.h <<\_ACEOF
#define WITH_DHCP 1
_ACEOF
- ;;
- *)
- ;;
- esac
-
fi
+
+
STATIC_MODULES=
# Check whether --with-static_modules was given.
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files ./Make.inc ./src/include/build-radpaths-h ./src/main/Makefile ./src/main/checkrad.pl ./src/main/radlast ./src/main/radtest ./scripts/rc.radiusd ./scripts/radwatch ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radrelay.conf ./raddb/radiusd.conf"
+ ac_config_files="$ac_config_files ./Make.inc ./src/include/build-radpaths-h ./src/main/Makefile ./src/main/radsniff.mk ./src/main/checkrad.pl ./src/main/radlast ./src/main/radtest ./scripts/rc.radiusd ./scripts/radwatch ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radrelay.conf ./raddb/radiusd.conf"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
fi
dnl extra argument: --with-dhcp
+WITH_DHCP=yes
AC_ARG_WITH(dhcp,
-[ --with-dhcp Compile in DHCP support. (default=no)],
+[ --with-dhcp Compile in DHCP support. (default=yes)],
[ case "$withval" in
yes)
- AC_DEFINE(WITH_DHCP, [1], [Include experimental support for DHCP])
- ;;
+ ;;
*)
- ;;
+ WITH_DHCP=no
esac ]
)
+if test "x$WITH_DHCP" = "xyes"; then
+ AC_DEFINE(WITH_DHCP, [1], [define if you want DHCP support])
+fi
dnl #
./Make.inc \
./src/include/build-radpaths-h \
./src/main/Makefile \
+ ./src/main/radsniff.mk \
./src/main/checkrad.pl \
./src/main/radlast \
./src/main/radtest \
--- /dev/null
+# Options for the FreeRADIUS deamon.
+#FREERADIUS_OPTIONS="-d /etc/freeradius"
+
PIDFILE="/var/run/freeradius/freeradius.pid"
DESCR="FreeRADIUS daemon"
+if [ -r /etc/default/$PROG ]; then
+ . /etc/default/$PROG
+fi
+
test -f $PROGRAM || exit 0
# /var/run may be a tmpfs
case "$1" in
start)
log_daemon_msg "Starting $DESCR" "$PROG"
- start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $PROGRAM || ret=$?
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $PROGRAM -- $FREERADIUS_OPTIONS || ret=$?
log_end_msg $ret
exit $ret
;;
etc/freeradius/hints
etc/freeradius/huntgroups
etc/freeradius/ldap.attrmap
-etc/freeradius/modules/*
+etc/freeradius/mods-available/*
etc/freeradius/policy.conf
etc/freeradius/policy.txt
etc/freeradius/preproxy_users
@@ -8,7 +8,7 @@
SRCS = rlm_sqlippool.c
HEADERS = $(top_builddir)/src/modules/rlm_sql/rlm_sql.h
- RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_sql $(INCLTDL)
+ RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_sql
-RLM_LIBS =
+RLM_LIBS += $(top_builddir)/src/modules/rlm_sql/.libs/rlm_sql.la
RLM_INSTALL =
--- /dev/null
+diff --git a/raddb/mods-available/sql b/raddb/mods-available/sql
+index 690c3a2..ec33ed1 100644
+--- a/raddb/mods-available/sql
++++ b/raddb/mods-available/sql
+@@ -103,5 +103,5 @@ sql {
+ nas_table = "nas"
+
+ # Read driver-specific configuration
+- $INCLUDE sql/${database}/dialup.conf
++ #$INCLUDE sql/${database}/dialup.conf
+ }
+diff --git a/raddb/mods-available/sqlippool b/raddb/mods-available/sqlippool
+index 94fabc0..aa9ea6b 100644
+--- a/raddb/mods-available/sqlippool
++++ b/raddb/mods-available/sqlippool
+@@ -46,7 +46,7 @@ sqlippool {
+ # same as the "database" field of the SQL module referred to in the
+ # "sql-instance-name", above.
+ #
+-$INCLUDE sql/postgresql/ippool.conf
++#$INCLUDE sql/mysql/ippool.conf
+
+ ## Logging configuration. (Comment out to disable logging)
+ sqlippool_log_exists = "Existing IP: %{reply:Framed-IP-Address} \
+@@ -63,5 +63,4 @@ $INCLUDE sql/postgresql/ippool.conf
+
+ sqlippool_log_nopool = "No Pool-Name defined \
+ (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+-
+ }
* Moved eap.conf to modules/eap
* Moved sql.conf to modules/sql
* Preliminary support for Apple's Grand Central Dispatch.
+ * All modules have been moved to raddb/mods-available/
+ and raddb/modes-enabled/. See raddb/README for more details.
* Largely config-file compatible with 2.1.x.
+ * For upgrade instructions, see raddb/README
Bug fixes
* All known bug fixes are included.
--- /dev/null
+SUBMAKEFILES := src/all.mk
-.TH RADWHO 1 "7 April 2005" "" "FreeRADIUS Daemon"
+.TH RADWHO 1 "26 Dec 2011" "" "FreeRADIUS Daemon"
.SH NAME
radwho - show online users
.SH SYNOPSIS
.RB [ \-d
.IR raddb_directory ]
.RB [ \-f ]
+.RB [ \-F
+.IR radutmp_file ]
.RB [ \-i ]
.RB [ \-n ]
.RB [ \-N
.IP \-f
Behave as the 'fingerd' daemon - waits for one line of input, then
prints the output with lines \\r\\n terminated.
+.IP \-F\ \fIradutmp_file\fP
+The file that contains the radutmp file. If this is specified, -d is
+not necessary.
.IP \-i
Shows the session ID instead of the full name.
.IP \-n
attrs.pre-proxy clients.conf dictionary templates.conf \
experimental.conf hints huntgroups ldap.attrmap \
policy.txt preproxy_users proxy.conf radiusd.conf trigger.conf \
- users policy.conf attrs.access_challenge
+ users policy.conf attrs.access_challenge README
+
+DEFAULT_SITES = default inner-tunnel
+
+DEFAULT_MODULES = acct_unique always attr_filter attr_rewrite chap checkval \
+ counter cui detail detail.log digest dynamic_clients eap \
+ echo exec expiration expr files inner-eap linelog logintime \
+ mschap ntlm_auth pap passwd preprocess radutmp realm \
+ replicate soh sradutmp unix utf8 wimax
#
# This target is here for local debugging
#
-all:
+all: sites-enabled mods-enabled
+
+.PHONY: sites-enabled
+sites-enabled:
@if [ ! -d sites-enabled ]; then \
mkdir sites-enabled; \
fi
- @if [ ! -f sites-enabled/default ]; then \
- cd sites-enabled && ln -s ../sites-available/default; \
- fi
- @if [ ! -f sites-enabled/inner-tunnel ]; then \
- cd sites-enabled && ln -s ../sites-available/inner-tunnel; \
- fi
-ifneq "${OPENSSL_INCLUDE}" ""
- @if [ ! -f sites-enabled/tls ]; then \
- cd sites-enabled && ln -s ../sites-available/tls; \
+ @cd sites-enabled/; \
+ for x in $(DEFAULT_SITES); do \
+ if [ ! -f $$x ]; then \
+ ln -s ../sites-available/$$x; \
+ fi; \
+ done
+
+.PHONY: mods-enabled
+mods-enabled:
+ @if [ ! -d mods-enabled ]; then \
+ mkdir mods-enabled; \
fi
-endif
+ @cd mods-enabled/; \
+ for x in $(DEFAULT_MODULES); do \
+ if [ ! -f $$x ]; then \
+ ln -s ../mods-available/$$x; \
+ fi; \
+ done
install:
$(INSTALL) -d -m 750 $(R)$(raddbdir)
$(INSTALL) -d -m 750 $(R)$(raddbdir)/sites-available
$(INSTALL) -d -m 750 $(R)$(raddbdir)/sites-enabled
- $(INSTALL) -d -m 750 $(R)$(raddbdir)/modules
+ $(INSTALL) -d -m 750 $(R)$(raddbdir)/mods-available
+ $(INSTALL) -d -m 750 $(R)$(raddbdir)/mods-enabled
@echo "Creating/updating files in $(R)$(raddbdir)"; \
- for i in $(FILES) `find sites-available/ modules/ -type f -print | sed 's/.*CVS.*//;s/.*~//;s/.*#.*//' `; do \
+ for i in $(FILES) `find sites-available/ mods-available/ -type f -print | sed 's/.*~//;s/.*#.*//' `; do \
[ ! -f $(R)$(raddbdir)/$$i ] && $(INSTALL) -m 640 $$i $(R)$(raddbdir)/$$i; \
if [ "`find $$i -newer $(R)$(raddbdir)/$$i`" ]; then \
echo "** $(R)$(raddbdir)/$$i"; \
fi; \
done; \
fi
- if [ ! -f $(R)$(raddbdir)/sites-enabled/default ]; then \
- cd $(R)$(raddbdir)/sites-enabled/; \
- ln -s ../sites-available/default; \
- fi
- if [ ! -f $(R)$(raddbdir)/sites-enabled/inner-tunnel ]; then \
- cd $(R)$(raddbdir)/sites-enabled/; \
- ln -s ../sites-available/inner-tunnel; \
- fi
- if [ ! -f $(R)$(raddbdir)/sites-enabled/control-socket ]; then \
- cd $(R)$(raddbdir)/sites-enabled/; \
- ln -s ../sites-available/control-socket; \
- fi
-ifneq "${OPENSSL_INCLUDE}" ""
- if [ ! -f $(R)$(raddbdir)/sites-enabled/control-socket ]; then \
- cd $(R)$(raddbdir)/sites-enabled/; \
- ln -s ../sites-available/control-socket; \
- fi
-endif
+ @cd $(R)$(raddbdir)/sites-enabled/; \
+ for x in $(DEFAULT_SITES); do \
+ if [ ! -f $$x ]; then \
+ ln -s ../sites-available/$$x; \
+ fi; \
+ done
+ @cd $(R)$(raddbdir)/mods-enabled/; \
+ for x in $(DEFAULT_MODULES); do \
+ if [ ! -f $$x ]; then \
+ ln -s ../mods-available/$$x; \
+ fi; \
+ done
clean:
- @rm -rf sites-enabled/inner-tunnel sites-enabled/default \
- sites-enabled/tls
+ @rm -rf *~ $(addprefix sites-enabled/,$(DEFAULT_SITES)) \
+ $(addprefix mods-enabled/,$(DEFAULT_MODULES))
triggers:
@grep exec_trigger `find ../src -name "*.c" -print` | grep '"' | sed -e 's/.*,//' -e 's/ *"//' -e 's/");.*//'
--- /dev/null
+Upgrading to Version 3.0
+========================
+
+The configuration for 3.0 is *largely* compatible with the 2.x
+configuration. However, it is NOT possible to simply use the 2.x
+configuration as-is. Instead, you should re-create it.
+
+Security
+--------
+
+A number of configuration items have moved into the "security"
+subsection of radiusd.conf. If you use these, you should move them.
+Otherwise, they can be ignored.
+
+The list of moved options is:
+
+ chroot
+ user
+ group
+ allow_core_dumps
+ reject_delay
+ status_server
+
+
+Modules Directory
+-----------------
+
+ As of version 3.0, the "modules" directory no longer exists.
+
+ Instead, all "example" modules have been put into the
+"mods-available" directory. Modules which can be loaded by the server
+are placed in the "mods-enabled" directory.
+
+ Modules can be enabled by creating a soft link. For module "foo", do:
+
+ $ cd raddb
+ $ ln -s mods-available/foo mods-enabled/foo
+
+ To create "local" versions of the modules, we suggest copying the
+file instead. This leaves the original file (with documentation) in
+the "mods-available" directory. Local changes should go into the
+"mods-enabled" directory.
+
+
+SQL
+---
+
+ The SQL configuration has been moved from sql.conf to mods-available/sql.
+The sqlippool.conf file has also been moved.
+
+ The SQL module configuration has been changed. The old connection
+pool options are no longer understood:
+
+ num_sql_socks
+ connect_failure_retry_delay
+ lifetime
+ max_queries
+
+ Instead, a connection pool configuration is used. This
+configuration contains all of the functionality of the previous
+configuration, but in a more generic form. It also is used in
+multiple modules, meaning that there are fewer different configuration
+items. The mapping between the configuration items is:
+
+ num_sql_socks -> pool { max }
+ connect_failure_retry_delay -> NOT SUPPORTED
+ lifetime -> pool { lifetime }
+ max_queries -> pool { uses }
+
+ The pool configuration adds a number of new configuration options,
+which allow the administrator to better control how FreeRADIUS uses
+SQL connection pools.
+
+
+EAP
+---
+
+ The EAP configuration has been moved from eap.conf to mods-available/eap.
+
+ It is otherwise unchanged. You chould be able to copy your old
+eap.conf file directly to mods-enabled/eap.
+
+
+RadSec
+------
+
+ RadSec (or RADIUS over TLS) is now supported. RADIUS over bare TCP
+is also supported, but is recommended only for secure networks.
+
+ See sites-available/tls for complete details on using TLS. The
+server can both receive incoming TLS connections, and also originate
+outgoing TLS connections.
+
+ The TLS configuration is taken from the old EAP-TLS configuration.
+It is largely identical to the old EAP-TLS configuration, so it should
+be simple to use and configure. It re-uses much of the EAP-TLS code,
+too.
+
# Ideally, the "configure" process should automatically enable this
# dictionary, but we don't yet do that.
#
-#$INCLUDE @prefix@/dictionary.dhcp
+#$INCLUDE @prefix@/share/freeradius/dictionary.dhcp
#
# The filename given here should be an absolute path.
# people from seeing that information.
detailperm = 0600
+ # The Unix group of the log file.
+ #
+ # The user that the server runs as must be in the specified
+ # system group otherwise this will fail to work.
+ #
+# group = freerad
+
#
# Every entry in the detail file has a header which
# is a timestamp. By default, we use the ctime
--- /dev/null
+## Configuration for DHCP to use SQL IP Pools.
+##
+## See sqlippool.conf for common configuration explanation
+##
+## $Id$
+
+sqlippool dhcp_sqlippool {
+ sql-instance-name = "sql"
+
+ ippool_table = "radippool"
+
+ lease-duration = 7200
+
+ # Client's MAC address is mapped to Calling-Station-Id in policy.conf
+ pool-key = "%{Calling-Station-Id}"
+
+ # For now, it only works with MySQL.
+ $INCLUDE ${confdir}/sql/mysql/ippool-dhcp.conf
+
+ sqlippool_log_exists = "DHCP: Existing IP: %{reply:Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ sqlippool_log_success = "DHCP: Allocated IP: %{reply:Framed-IP-Address} from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ sqlippool_log_clear = "DHCP: Released IP %{Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})"
+
+ sqlippool_log_failed = "DHCP: IP Allocation FAILED from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ sqlippool_log_nopool = "DHCP: No Pool-Name defined (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+}
CA_file = ${cadir}/ca.pem
#
+ # If OpenSSL supports TLS-PSK, then we can use
+ # a PSK identity and (hex) password. When the
+ # following two configuration items are specified,
+ # then certificate-based configuration items are
+ # not allowed. e.g.:
+ #
+ # private_key_password
+ # private_key_file
+ # certificate_file
+ # CA_file
+ # CA_path
+ #
+ # For now, the identity is fixed, and must be the
+ # same on the client. The passphrase must be a hex
+ # value, and can be up to 256 hex digits.
+ #
+ # Future versions of the server may be able to
+ # look up the shared key (hexphrase) based on the
+ # identity.
+ #
+ # psk_identity = "test"
+ # psk_hexphrase = "036363823"
+
+ #
# For DH cipher suites to work, you have to
# run OpenSSL to create the DH file first:
#
# Responder is running as a vhost.
#
url = "http://127.0.0.1/ocsp/"
+
+ #
+ # If the OCSP Responder can not cope with nonce
+ # in the request, then it can be disabled here.
+ #
+ # For security reasons, disabling this option
+ # is not recommended as nonce protects against
+ # replay attacks.
+ #
+ # Note that Microsoft AD Certificate Services OCSP
+ # Responder does not enable nonce by default. It is
+ # more secure to enable nonce on the responder than
+ # to disable it in the query here.
+ # See http://technet.microsoft.com/en-us/library/cc770413%28WS.10%29.aspx
+ #
+ # use_nonce = yes
+
+ #
+ # Number of seconds before giving up waiting
+ # for OCSP response. 0 uses system default.
+ #
+ # timeout = 0
+
+ #
+ # Normally an error in querying the OCSP
+ # responder (no response from server, server did
+ # not understand the request, etc) will result in
+ # a validation failure.
+ #
+ # To treat these errors as 'soft' failures and
+ # still accept the certificate, enable this
+ # option.
+ #
+ # Warning: this may enable clients with revoked
+ # certificates to connect if the OCSP responder
+ # is not available. Use with caution.
+ #
+ # softfail = no
}
}
permissions = 0600
#
+ # The Unix group of the log file.
+ #
+ # The user that freeradius runs as must be in the specified
+ # group, otherwise it will not be possible to set the group.
+ #
+ # group = freerad
+
+ #
# The default format string.
format = "This is a log message for %{User-Name}"
# Attributes marked as '=' are added to reply_items instead
# of default configure_itmes
#
-# Attributse marked as '~' are added to request_items
+# Attributes marked as '~' are added to request_items
#
# Field marked as ',' may contain a comma separated list
# of attributes.
#
-# hashsize - hashtable size. If 0 or not specified records are not
-# stored in memory and file is read on every request.
-# This configuration is *not* recommended, as it can be
-# very slow. The "passwd" module reloads its configuration
-# on HUP, so setting "hashsize = 0" is unnecessary.
+# hashsize - hashtable size. Setting it to 0 is no longer permitted
+# A future version of the server will have the module
+# automatically determine the hash size. Having it set
+# manually should not be necessary.
#
# allowmultiplekeys - if many records for a key are allowed
#
# lifetime
# max_queries
+ # The connection pool is new for 3.0, and will be used in many
+ # modules, for all kinds of connection-related activity.
+ #
pool {
# Number of connections to start
start = 5
min = 4
# Maximum number of connections
+ #
+ # If these connections are all in use and a new one
+ # is requested, the request will NOT get a connection.
max = 10
# Spare connections to be left idle
+ #
+ # NOTE: Idle connections WILL be closed if "idle_timeout"
+ # is set.
spare = 3
# Number of uses before the connection is closed
# idle timeout (in seconds). A connection which is
# unused for this length of time will be closed.
idle_timeout = 60
+
+ # NOTE: All configuration settings are enforced. If a
+ # connection is closed because of "idle_timeout",
+ # "uses", or "lifetime", then the total number of
+ # connections MAY fall below "min". When that
+ # happens, it will open a new connection. It will
+ # also log a WARNING message.
+ #
+ # The solution is to either lower the "min" connections,
+ # or increase lifetime/idle_timeout.
}
# Set to 'yes' to read radius clients from the database ('nas' table)
noop
}
}
+
+ # Assign compatibility data to request for sqlippool
+ dhcp_sqlippool.post-auth {
+
+
+ # Do some minor hacks to the request so that it looks
+ # like a RADIUS request to the SQL IP Pool module.
+ update request {
+ User-Name = "DHCP-%{DHCP-Client-Hardware-Address}"
+ Calling-Station-Id = "%{DHCP-Client-Hardware-Address}"
+ NAS-IP-Address = "%{%{DHCP-Gateway-IP-Address}:-127.0.0.1}"
+ Acct-Status-Type = Start
+ }
+
+ # Call the actual module
+ dhcp_sqlippool
+
+ # Convert Framed-IP-Address to DHCP, but only if we
+ # actually allocated an address.
+ if (ok) {
+ update reply {
+ DHCP-Your-IP-Address = "%{reply:Framed-IP-Address}"
+ }
+ }
+ }
}
#
#
- # As of 2.0.5, most of the module configurations are in a
- # sub-directory. Files matching the regex /[a-zA-Z0-9_.]+/
- # are loaded. The modules are initialized ONLY if they are
- # referenced in a processing section, such as authorize,
- # authenticate, accounting, pre/post-proxy, etc.
+ # As of 3.0, modules are in mods-enabled/. Files matching
+ # the regex /[a-zA-Z0-9_.]+/ are loaded. The modules are
+ # initialized ONLY if they are referenced in a processing
+ # section, such as authorize, authenticate, accounting,
+ # pre/post-proxy, etc.
#
- $INCLUDE ${confdir}/modules/
+ $INCLUDE ${confdir}/mods-enabled/
}
# Instantiation
--- /dev/null
+server chbind{
+ authorize {
+ if (GSS-Acceptor-Service-Name && outer.request:GSS-Acceptor-Service-Name != GSS-Acceptor-Service-Name ) {
+ reject
+ }
+ update reply {
+ GSS-Acceptor-Service-NAME == "%{GSS-ACCEPTOR-SERVICE-Name}"
+ GSS-ACCEPTOR-Host-Name == "%{GSS-Acceptor-Host-Name}"
+ GSS-Acceptor-Realm-Name == "%{GSS-Acceptor-Realm-Name}"
+ }
+ if (GSS-Acceptor-Service-Name || GSS-Acceptor-Realm-Name || GSS-Acceptor-Host-Name) {
+ update control {
+ Chbind-Response-Code := success
+ }
+ }
+ handled
+ }
+}
+
# ...
#}
+ # Or, allocate IPs from the DHCP pool in SQL.
+# dhcp_sqlippool
+
ok
}
# ...
#}
+ # Or, allocate IPs from the DHCP pool in SQL.
+# dhcp_sqlippool
+
ok
}
--- /dev/null
+# -*- text -*-
+##
+## ippool-dhcp.conf -- MySQL queries for sqlippool-dhcp instance
+## Only post-auth method is used
+##
+## $Id$
+
+## This series of queries allocates an IP address
+## First, clear expired entries
+ allocate-clear = "UPDATE ${ippool_table} \
+ SET nasipaddress = '', pool_key = 0, \
+ callingstationid = '', username = '', \
+ expiry_time = NULL \
+ WHERE expiry_time <= NOW() - INTERVAL 1 SECOND \
+ "
+
+## Then find an available IP address
+## The ORDER BY clause of this query tries to allocate the same IP address
+## which user had last session regardless of expiry time
+## to handle DHCP request and duplicates from the same client
+allocate-find = "SELECT framedipaddress FROM ${ippool_table} \
+ WHERE pool_name = '%{control:Pool-Name}' AND \
+ ( \
+ (callingstationid = '%{Calling-Station-Id}') OR \
+ (expiry_time < NOW() OR expiry_time IS NULL) \
+ ) \
+ ORDER BY (callingstationid = '%{Calling-Station-Id}') DESC, \
+ expiry_time DESC\
+ LIMIT 1 \
+ FOR UPDATE"
+
+## If an IP could not be allocated, check to see if the pool exists or not
+## This allows the module to differentiate between a full pool and no pool
+## Note: If you are not running redundant pool modules this query may be
+## commented out to save running this query every time an ip is not allocated.
+pool-check = "SELECT id FROM ${ippool_table} \
+ WHERE pool_name='%{control:Pool-Name}' LIMIT 1"
+
+
+## This is the final IP Allocation query, which saves the allocated ip details
+allocate-update = "UPDATE ${ippool_table} \
+ SET nasipaddress = '%{NAS-IP-Address}', pool_key = '${pool-key}', \
+ callingstationid = '%{Calling-Station-Id}', username = '%{User-Name}', \
+ calledstationid = 'Freeradius-DHCP', \
+ expiry_time = GREATEST( \
+ IF(ISNULL(expiry_time),'0000-00-00 00:00:00',expiry_time), \
+ NOW() + INTERVAL ${lease-duration} SECOND) \
+ WHERE framedipaddress = '%I' AND \
+ ( \
+ (callingstationid = '%{Calling-Station-Id}') OR \
+ (expiry_time < NOW() OR expiry_time IS NULL) \
+ ) \
+ "
+
+## This series of queries frees an IP number when an accounting
+## START record arrives. Unused, but must be set to non-empty query
+start-update = "SELECT NOW()"
+
+## This series of queries frees an IP number when an accounting
+## STOP record arrives. Unused, but must be set to non-empty query
+stop-clear = "SELECT NOW()"
+
+## This series of queries frees an IP number when an accounting
+## ALIVE record arrives. Unused, but must be set to non-empty query
+alive-update = "SELECT NOW()"
+
+## This series of queries frees the IP numbers allocate to a
+## NAS when an accounting ON record arrives. Unused, but must be set
+## to non-empty query
+on-clear = "SELECT NOW()"
+
+## This series of queries frees the IP numbers allocate to a
+## NAS when an accounting OFF record arrives. Unused, but must be set
+## to non-empty query
+off-clear = "SELECT NOW()"
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/clients.conf
%config(noreplace) /etc/raddb/hints
%config(noreplace) /etc/raddb/huntgroups
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sqlippool.conf
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/preproxy_users
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/proxy.conf
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/radiusd.conf
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sql.conf
%dir %attr(750,root,radiusd) /etc/raddb/sql
#%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sql/oracle/*
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/users
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sites-available/*
%dir %attr(750,root,radiusd) /etc/raddb/sites-enabled
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sites-enabled/*
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/eap.conf
%config(noreplace) %attr(640,root,radiusd) /etc/raddb/example.pl
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/policy.conf
%config(noreplace) /etc/raddb/policy.txt
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/templates.conf
%dir %attr(750,root,radiusd) /etc/raddb/modules
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/acct_unique
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/always
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/attr_filter
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/attr_rewrite
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/chap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/checkval
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/counter
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/cui
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail.example.com
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail.log
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/digest
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/dynamic_clients
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/echo
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/etc_group
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/exec
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/expiration
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/expr
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/files
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/inner-eap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/ippool
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/logintime
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/linelog
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mac2ip
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mac2vlan
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mschap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/ntlm_auth
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/opendirectory
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/otp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/pam
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/pap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/perl
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/passwd
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/policy
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/preprocess
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/radutmp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/realm
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/redis
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/rediswho
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/replicate
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/smbpasswd
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/smsotp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/soh
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sql_log
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sqlcounter_expire_on_login
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sradutmp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/unix
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/wimax
+%dir %attr(750,root,radiusd) /etc/raddb/mods-available
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-available/*
+%dir %attr(750,root,radiusd) /etc/raddb/mods-enabled
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-enabled/*
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/*
%dir %attr(755,radiusd,radiusd) /var/run/radiusd/
# binaries
%defattr(-,root,root)
--- /dev/null
+# boilermake: A reusable, but flexible, boilerplate Makefile.
+#
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Caution: Don't edit this Makefile! Create your own main.mk and other
+# submakefiles, which will be included by this Makefile.
+# Only edit this if you need to modify boilermake's behavior (fix
+# bugs, add features, etc).
+
+# Note: Parameterized "functions" in this makefile that are marked with
+# "USE WITH EVAL" are only useful in conjuction with eval. This is
+# because those functions result in a block of Makefile syntax that must
+# be evaluated after expansion. Since they must be used with eval, most
+# instances of "$" within them need to be escaped with a second "$" to
+# accomodate the double expansion that occurs when eval is invoked.
+
+# ADD_CLEAN_RULE - Parameterized "function" that adds a new rule and phony
+# target for cleaning the specified target (removing its build-generated
+# files).
+#
+# USE WITH EVAL
+#
+define ADD_CLEAN_RULE
+ clean: clean_$(notdir ${1})
+ .PHONY: clean_$(notdir ${1})
+ clean_$(notdir ${1}):
+ @$(strip rm -f ${${1}_BUILD}/${1} ${${1}_NOLIBTOOL} ${${1}_BUILD}/${${1}_RELINK} $${${1}_OBJS} $${${1}_DEPS} $${${1}_OBJS:%.${OBJ_EXT}=%.[do]}) $(if ${TARGET_DIR},$${TARGET_DIR}/$(notdir ${1}))
+ $${${1}_POSTCLEAN}
+
+endef
+
+# FILTER_DEPENDS: function to turn a *.d file into a *.mk file.
+# We start off with the dependencies as created by the compiler,
+# CPP, or makedepend. We then ensure that there is an empty dependency
+# for each header file. The blank target ensures that the build
+# can proceed even if the header file has been deleted.
+#
+# COMMON filters:
+# remove comments
+# remove dependencies on global include files
+# remove empty dependencies
+# remove CPP hacks like "foo: <built-in>"
+#
+# 1) Filter the .d file to remove unnecessary cruft
+#
+# COMMON
+# Replace ".o" with "${OBJ_EXT}"
+# delete empty continuation lines
+# delete blank lines
+# replace "build/" with "${BUILD_DIR}/" when it's at the start of a line
+# delete references to ${BUILD_DIR}/make/include, the "config.mk"
+# file adds these dependencies automatically.
+# replace "build/" with "${BUILD_DIR}/" when it's in the middle of a line
+#
+# remove sequential duplicate lines
+#
+# 2) Create empty dependencies from the files
+#
+# COMMON
+# remove existing targets
+# remove continuations (to make the targets stand by themselves)
+# delete blank lines
+# add in empty dependency for each file.
+# remove sequential duplicate lines
+#
+define FILTER_DEPENDS
+ @mkdir -p $$(dir $${BUILD_DIR}/make/src/$$*)
+ @mkdir -p $$(dir $${BUILD_DIR}/objs/$$*)
+ @sed -e 's/#.*//' \
+ -e 's,^$${top_srcdir},$$$${top_srcdir},' \
+ -e 's, $${top_srcdir}, $$$${top_srcdir},' \
+ -e 's,^$${BUILD_DIR},$$$${BUILD_DIR},' \
+ -e 's, $${BUILD_DIR}/make/include/[^ :]*,,' \
+ -e 's, $${BUILD_DIR}, $$$${BUILD_DIR},' \
+ -e 's, /[^: ]*,,g' \
+ -e 's,^ *[^:]* *: *$$$$,,' \
+ -e '/: </ d' \
+ -e 's/\.o: /.$$$${OBJ_EXT}: /' \
+ -e '/^ *\\$$$$/ d' \
+ < $${BUILD_DIR}/objs/$$*.d | sed -e '$$$$!N; /^\(.*\)\n\1$$$$/!P; D' \
+ > $${BUILD_DIR}/make/src/$$*.mk
+ @sed -e 's/#.*//' \
+ -e 's, $${BUILD_DIR}/make/include/[^ :]*,,' \
+ -e 's, /[^: ]*,,g' \
+ -e 's,^ *[^:]* *: *$$$$,,' \
+ -e '/: </ d' \
+ -e 's/^[^:]*: *//' \
+ -e 's/ *\\$$$$//' \
+ -e 's/$$$$/ :/' \
+ < $${BUILD_DIR}/objs/$$*.d | sed -e '$$$$!N; /^\(.*\)\n\1$$$$/!P; D' \
+ >> $${BUILD_DIR}/make/src/$$*.mk
+ @rm -f $${BUILD_DIR}/objs/$$*.d
+endef
+
+# ADD_OBJECT_RULE - Parameterized "function" that adds a pattern rule, using
+# the commands from the second argument, for building object files from
+# source files with the filename extension specified in the first argument.
+#
+# This function assumes that the C/C++ sources files have filenames
+# *relative* to the source root. If they have absolute pathnames, it
+# creates the wrong filenames...
+#
+# USE WITH EVAL
+#
+ifeq "${CPP_MAKEDEPEND}" "yes"
+define ADD_OBJECT_RULE
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1}
+ ${2}
+ $${CPP} $${CPPFLAGS} $${SRC_INCDIRS} $${SRC_DEFS} $$< | sed \
+ -n 's,^\# *[0-9][0-9]* *"\([^"]*\)".*,$$@: \1,p' > $${BUILD_DIR}/objs/$$*.d
+${FILTER_DEPENDS}
+endef
+
+else
+define ADD_OBJECT_RULE
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1}
+ ${2}
+${FILTER_DEPENDS}
+endef
+endif
+
+# ADD_TARGET_DIR - Parameterized "function" that makes a link from
+# TARGET_DIR to the executable or library in the BUILD_DIR directory.
+#
+# USE WITH EVAL
+#
+ifneq "${TARGET_DIR}" ""
+ define ADD_TARGET_DIR
+ all: $${TARGET_DIR}/$$(notdir ${1})
+
+ $${TARGET_DIR}/$$(notdir ${1}): ${1}
+ [ -f $${TARGET_DIR}/$$(notdir ${1}) ] || ln -s ${1} $${TARGET_DIR}/$$(notdir ${1})
+
+ endef
+endif
+
+# ADD_TARGET_TO_ALL - Parameterized "function" that adds the target,
+# and makes "all" depend on it.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_TO_ALL
+ all: ${1}
+
+endef
+
+# ADD_TARGET_RULE.* - Parameterized "functions" that adds a new target to the
+# Makefile. There should be one ADD_TARGET_RULE definition for each
+# type of target that is used in the build.
+#
+# New rules can be added by copying one of the existing ones, and
+# replacing the line after the "mkdir"
+#
+
+# ADD_TARGET_RULE.exe - Build an executable target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.exe
+ # So "make ${1}" works
+ .PHONY: ${1}
+ ${1}: $${${1}_BUILD}/${1}
+
+ # Create executable ${1}
+ $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_PRLIBS}
+ @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+ @$(ECHO) LINK $${${1}_BUILD}/${1}
+ @$${${1}_LINKER} -o $${${1}_BUILD}/${1} $${RPATH_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_PRLIBS} \
+ $${LDLIBS} $${${1}_LDLIBS}
+ @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_TARGET_RULE.a - Build a static library target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.a
+ # So "make ${1}" works
+ .PHONY: ${1}
+ ${1}: $${${1}_BUILD}/${1}
+
+ # Create static library ${1}
+ $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PREREQS}
+ @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+ @$(ECHO) LINK $${${1}_BUILD}/${1}
+ @$${AR} $${ARFLAGS} $${${1}_BUILD}/${1} $${${1}_OBJS}
+ @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_TARGET_RULE.so - Build a ".so" target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.so
+$(error Please add rules to build a ".so" file.)
+endef
+
+# ADD_TARGET_RULE.dll - Build a ".dll" target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.dll
+$(error Please add rules to build a ".dll" file.)
+endef
+
+# ADD_TARGET_RULE.dylib - Build a ".dylib" target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.dylib
+$(error Please add rules to build a ".dylib" file.)
+endef
+
+# CANONICAL_PATH - Given one or more paths, converts the paths to the canonical
+# form. The canonical form is the path, relative to the project's top-level
+# directory (the directory from which "make" is run), and without
+# any "./" or "../" sequences. For paths that are not located below the
+# top-level directory, the canonical form is the absolute path (i.e. from
+# the root of the filesystem) also without "./" or "../" sequences.
+define CANONICAL_PATH
+$(patsubst ${CURDIR}/%,%,$(abspath ${1}))
+endef
+
+# COMPILE_C_CMDS - Commands for compiling C source code.
+define COMPILE_C_CMDS
+ @mkdir -p $(dir $@)
+ @$(ECHO) CC $<
+ @$(strip ${COMPILE.c} -o $@ -c -MD ${CFLAGS} ${SRC_CFLAGS} ${INCDIRS} \
+ ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
+endef
+
+# COMPILE_CXX_CMDS - Commands for compiling C++ source code.
+define COMPILE_CXX_CMDS
+ @mkdir -p $(dir $@)
+ @$(strip ${COMPILE.cxx} -o $@ -c -MD ${CXXFLAGS} ${SRC_CXXFLAGS} ${INCDIRS} \
+ ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
+endef
+
+# INCLUDE_SUBMAKEFILE - Parameterized "function" that includes a new
+# "submakefile" fragment into the overall Makefile. It also recursively
+# includes all submakefiles of the specified submakefile fragment.
+#
+# USE WITH EVAL
+#
+define INCLUDE_SUBMAKEFILE
+ # Initialize all variables that can be defined by a makefile fragment, then
+ # include the specified makefile fragment.
+ TARGET :=
+ TGT_LDFLAGS :=
+ TGT_LDLIBS :=
+ TGT_LINKER :=
+ TGT_POSTCLEAN :=
+ TGT_POSTMAKE :=
+ TGT_PREREQS :=
+ TGT_POSTINSTALL :=
+ TGT_INSTALLDIR := ..
+ TGT_CHECK_HEADERS :=
+ TGT_CHECK_LIBS :=
+
+ SOURCES :=
+ SRC_CFLAGS :=
+ SRC_CXXFLAGS :=
+ SRC_DEFS :=
+ SRC_INCDIRS :=
+ MAN :=
+
+ SUBMAKEFILES :=
+
+ # A directory stack is maintained so that the correct paths are used as we
+ # recursively include all submakefiles. Get the makefile's directory and
+ # push it onto the stack.
+ DIR := $(call CANONICAL_PATH,$(dir ${1}))
+ DIR_STACK := $$(call PUSH,$${DIR_STACK},$${DIR})
+
+ include ${1}
+
+ # Initialize internal local variables.
+ OBJS :=
+
+ # Determine which target this makefile's variables apply to. A stack is
+ # used to keep track of which target is the "current" target as we
+ # recursively include other submakefiles.
+ ifneq "$$(strip $${TARGET})" ""
+ # This makefile defined a new target. Target variables defined by this
+ # makefile apply to this new target. Initialize the target's variables.
+
+ # libs go into ${BUILD_DIR}/lib
+ # everything else goes into ${BUILD_DIR}/bin
+# TGT := $$(strip $$(if $$(suffix $${TARGET}),$${BUILD_DIR}/lib,$${BUILD_DIR}/bin)/$${TARGET})
+ TGT := $${TARGET}
+
+ # A "hook" to rewrite "libfoo.a" -> "libfoo.la" when using libtool
+ $$(eval $$(call ADD_LIBTOOL_SUFFIX))
+
+ ALL_TGTS += $${TGT}
+ $${TGT}_LDFLAGS := $${TGT_LDFLAGS}
+ $${TGT}_LDLIBS := $${TGT_LDLIBS}
+ $${TGT}_LINKER := $${TGT_LINKER}
+ $${TGT}_POSTMAKE := $${TGT_POSTMAKE}
+ $${TGT}_POSTCLEAN := $${TGT_POSTCLEAN}
+ $${TGT}_POSTINSTALL := $${TGT_POSTINSTALL}
+ $${TGT}_PREREQS := $${TGT_PREREQS}
+ $${TGT}_PRBIN := $$(addprefix $${BUILD_DIR}/bin/,$$(filter-out %.a %.so %.la,$${TGT_PREREQS}))
+ $${TGT}_PRLIBS := $$(addprefix $${BUILD_DIR}/lib/,$$(filter %.a %.so %.la,$${TGT_PREREQS}))
+ $${TGT}_DEPS :=
+ $${TGT}_OBJS :=
+ $${TGT}_SOURCES :=
+ $${TGT}_MAN := $${MAN}
+ $${TGT}_SUFFIX := $$(if $$(suffix $${TGT}),$$(suffix $${TGT}),.exe)
+ $${TGT}_BUILD := $$(if $$(suffix $${TGT}),$${BUILD_DIR}/lib,$${BUILD_DIR}/bin)
+ $${TGT}_MAKEFILES += ${1}
+ $${TGT}_CHECK_HEADERS := $${TGT_CHECK_HEADERS}
+ $${TGT}_CHECK_LIBS := $${TGT_CHECK_LIBS}
+ else
+ # The values defined by this makefile apply to the the "current" target
+ # as determined by which target is at the top of the stack.
+ TGT := $$(strip $$(call PEEK,$${TGT_STACK}))
+ $${TGT}_LDFLAGS += $${TGT_LDFLAGS}
+ $${TGT}_LDLIBS += $${TGT_LDLIBS}
+ $${TGT}_POSTCLEAN += $${TGT_POSTCLEAN}
+ $${TGT}_POSTMAKE += $${TGT_POSTMAKE}
+ $${TGT}_PREREQS += $${TGT_PREREQS}
+ endif
+
+ # Push the current target onto the target stack.
+ TGT_STACK := $$(call PUSH,$${TGT_STACK},$${TGT})
+
+ ifneq "$$(strip $${SOURCES})" ""
+ # This makefile builds one or more objects from source. Validate the
+ # specified sources against the supported source file types.
+ BAD_SRCS := $$(strip $$(filter-out $${ALL_SRC_EXTS},$${SOURCES}))
+ ifneq "$${BAD_SRCS}" ""
+ $$(error Unsupported source file(s) found in ${1} [$${BAD_SRCS}])
+ endif
+
+ # Qualify and canonicalize paths.
+ SOURCES := $$(call QUALIFY_PATH,$${DIR},$${SOURCES})
+ SOURCES := $$(call CANONICAL_PATH,$${SOURCES})
+ SRC_INCDIRS := $$(call QUALIFY_PATH,$${DIR},$${SRC_INCDIRS})
+ SRC_INCDIRS := $$(call CANONICAL_PATH,$${SRC_INCDIRS})
+
+ # Save the list of source files for this target.
+ $${TGT}_SOURCES += $${SOURCES}
+
+ # Convert the source file names to their corresponding object file
+ # names.
+ OBJS := $$(addprefix $${BUILD_DIR}/objs/,\
+ $$(addsuffix .${OBJ_EXT},$$(basename $${SOURCES})))
+
+ # Add the objects to the current target's list of objects, and create
+ # target-specific variables for the objects based on any source
+ # variables that were defined.
+ $${TGT}_OBJS += $${OBJS}
+ $${TGT}_DEPS += $$(addprefix $${BUILD_DIR}/make/src/,\
+ $$(addsuffix .mk,$$(basename $${SOURCES})))
+
+ # A "hook" to define variables needed by the "legacy" makefiles.
+ $$(eval $$(call ADD_LEGACY_VARIABLES,$$(dir ${1}),$${TGT}))
+
+ $${OBJS}: SRC_CFLAGS := $${SRC_CFLAGS}
+ $${OBJS}: SRC_CXXFLAGS := $${SRC_CXXFLAGS}
+ $${OBJS}: SRC_DEFS := $$(addprefix -D,$${SRC_DEFS})
+ $${OBJS}: SRC_INCDIRS := $$(addprefix -I,$${SRC_INCDIRS})
+ endif
+
+ ifneq "$$(strip $${SUBMAKEFILES})" ""
+ # This makefile has submakefiles. Recursively include them.
+ $$(foreach MK,$${SUBMAKEFILES},\
+ $$(eval $$(call INCLUDE_SUBMAKEFILE,\
+ $$(call CANONICAL_PATH,\
+ $$(call QUALIFY_PATH,$${DIR},$${MK})))))
+ endif
+
+ # Reset the "current" target to it's previous value.
+ TGT_STACK := $$(call POP,$${TGT_STACK})
+ # If we're about to change targets, create the rules for the target
+ ifneq "$${TGT}" "$$(call PEEK,$${TGT_STACK})"
+ # add rules to build the target, and have "all" depend on it.
+ $$(eval $$(call ADD_TARGET_TO_ALL,$${TGT}))
+
+ # A "hook" to add rules for ${TARGET_DIR}/foo, if TARGET_DIR
+ # is defined. Otherwise, we leave the source directory untouched.
+ $$(eval $$(call ADD_TARGET_DIR,$${TGT}))
+
+ # A "hook" to build the libtool target.
+ $$(eval $$(call ADD_LIBTOOL_TARGET))
+
+ # Choose the correct linker.
+ ifeq "$$(strip $$(filter $${CXX_SRC_EXTS},$${$${TGT}_SOURCES}))" ""
+ ifeq "$${$${TGT}_LINKER}" ""
+ $${TGT}_LINKER := ${LL}$${LINK.c}
+ endif
+ else
+ ifeq "$${$${TGT}_LINKER}" ""
+ $${TGT}_LINKER := ${LL}$${LINK.cxx}
+ endif
+ endif
+
+ # add rules to build the target
+ $$(eval $$(call ADD_TARGET_RULE$${$${TGT}_SUFFIX},$${TGT}))
+
+ # generate the clean rule for this target.
+ $$(eval $$(call ADD_CLEAN_RULE,$${TGT}))
+
+ # Hook to add an installation target
+ $$(eval $$(call ADD_INSTALL_TARGET,$${TGT}))
+
+ # Hook to add a configuration target
+ $$(eval $$(call ADD_TARGET_CONFIG,$${TGT}))
+
+ # "hook" for legacy Makefiles
+ $$(eval $$(call ADD_LEGACY_RULE,$${TGT}))
+ endif
+
+ TGT := $$(call PEEK,$${TGT_STACK})
+
+ # Reset the "current" directory to it's previous value.
+ DIR_STACK := $$(call POP,$${DIR_STACK})
+ DIR := $$(call PEEK,$${DIR_STACK})
+endef
+
+# MIN - Parameterized "function" that results in the minimum lexical value of
+# the two values given.
+define MIN
+$(firstword $(sort ${1} ${2}))
+endef
+
+# PEEK - Parameterized "function" that results in the value at the top of the
+# specified colon-delimited stack.
+define PEEK
+$(lastword $(subst :, ,${1}))
+endef
+
+# POP - Parameterized "function" that pops the top value off of the specified
+# colon-delimited stack, and results in the new value of the stack. Note that
+# the popped value cannot be obtained using this function; use peek for that.
+define POP
+${1:%:$(lastword $(subst :, ,${1}))=%}
+endef
+
+# PUSH - Parameterized "function" that pushes a value onto the specified colon-
+# delimited stack, and results in the new value of the stack.
+define PUSH
+${2:%=${1}:%}
+endef
+
+# QUALIFY_PATH - Given a "root" directory and one or more paths, qualifies the
+# paths using the "root" directory (i.e. appends the root directory name to
+# the paths) except for paths that are absolute.
+define QUALIFY_PATH
+$(addprefix ${1}/,$(filter-out /%,${2})) $(filter /%,${2})
+endef
+
+###############################################################################
+#
+# Start of Makefile Evaluation
+#
+###############################################################################
+
+# Older versions of GNU Make lack capabilities needed by boilermake.
+# With older versions, "make" may simply output "nothing to do", likely leading
+# to confusion. To avoid this, check the version of GNU make up-front and
+# inform the user if their version of make doesn't meet the minimum required.
+MIN_MAKE_VERSION := 3.81
+MIN_MAKE_VER_MSG := boilermake requires GNU Make ${MIN_MAKE_VERSION} or greater
+ifeq "${MAKE_VERSION}" ""
+ $(info GNU Make not detected)
+ $(error ${MIN_MAKE_VER_MSG})
+endif
+ifneq "${MIN_MAKE_VERSION}" "$(call MIN,${MIN_MAKE_VERSION},${MAKE_VERSION})"
+ $(info This is GNU Make version ${MAKE_VERSION})
+ $(error ${MIN_MAKE_VER_MSG})
+endif
+
+# Define the source file extensions that we know how to handle.
+OBJ_EXT := o
+C_SRC_EXTS := %.c
+CXX_SRC_EXTS := %.C %.cc %.cp %.cpp %.CPP %.cxx %.c++
+ALL_SRC_EXTS := ${C_SRC_EXTS} ${CXX_SRC_EXTS}
+
+# Initialize global variables.
+ALL_TGTS :=
+DEFS :=
+DIR_STACK :=
+INCDIRS :=
+TGT_STACK :=
+
+ifeq "${top_builddir}" ""
+ top_builddir := .
+endif
+
+# Ensure that valid values are set for BUILD_DIR
+ifeq "$(strip ${BUILD_DIR})" ""
+ ifeq "${top_builddir}" "${PWD}"
+ BUILD_DIR := build
+ else
+ BUILD_DIR := ${top_builddir}/build
+ endif
+else
+ BUILD_DIR := $(call CANONICAL_PATH,${BUILD_DIR})
+endif
+
+# Define compilers and linkers
+#
+COMPILE.c = ${CC}
+COMPILE.cxx = ${CXX}
+CPP = cc -E
+LINK.c = ${CC}
+LINK.cxx = ${CXX}
+
+# Set ECHO to "true" for *very* quiet builds
+ECHO = echo
+
+# Define the "all" target (which simply builds all user-defined targets) as the
+# default goal.
+.PHONY: all
+all:
+
+# Add "clean" rules to remove all build-generated files.
+.PHONY: clean
+clean:
+
+top_makedir := $(dir $(lastword ${MAKEFILE_LIST}))
+
+-include ${top_makedir}/install.mk
+-include ${top_makedir}/libtool.mk
+
+# Include the main user-supplied submakefile. This also recursively includes
+# all other user-supplied submakefiles.
+$(eval $(call INCLUDE_SUBMAKEFILE,${top_builddir}/main.mk))
+
+# Perform post-processing on global variables as needed.
+DEFS := $(addprefix -D,${DEFS})
+INCDIRS := $(addprefix -I,$(call CANONICAL_PATH,${INCDIRS}))
+
+# Add pattern rule(s) for creating compiled object code from C source.
+$(foreach EXT,${C_SRC_EXTS},\
+ $(eval $(call ADD_OBJECT_RULE,${EXT},$${COMPILE_C_CMDS})))
+
+# Add pattern rule(s) for creating compiled object code from C++ source.
+$(foreach EXT,${CXX_SRC_EXTS},\
+ $(eval $(call ADD_OBJECT_RULE,${EXT},$${COMPILE_CXX_CMDS})))
+
+# Don't include the target dependencies if we're doing a "make clean"
+# Future: have a list of targets that don't require dependency generation,
+# and see if MAKECMDGOALS is one of them.
+ifneq "$(MAKECMDGOALS)" "clean"
+ $(foreach TGT,${ALL_TGTS},\
+ $(eval -include ${${TGT}_DEPS}))
+endif
--- /dev/null
+# boilermake: A reusable, but flexible, boilerplate Makefile.
+#
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# ADD_INSTALL_RULE.* - Parameterized "functions" that adds a new
+# installation to the Makefile. There should be one ADD_INSTALL_RULE
+# definition for each type of target that is used in the build.
+#
+# New rules can be added by copying one of the existing ones, and
+# replacing the line after the "mkdir"
+#
+
+# ADD_INSTALL_RULE.exe - Parameterized "function" that adds a new rule
+# and phony target for installing an executable.
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_RULE.exe
+ ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Global install depends on ${1}
+ install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Install executable ${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/$${RELINK}${1}
+ @$(ECHO) INSTALL ${1}
+ @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+ @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/bin/$${RELINK}${1} $${${1}_INSTALLDIR}/
+ @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.a - Parameterized "function" that adds a new rule
+# and phony target for installing a static library
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_RULE.a
+ ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Global install depends on ${1}
+ install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Install static library ${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): ${1}
+ @$(ECHO) INSTALL ${1}
+ @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+ @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/lib/${1} $${${1}_INSTALLDIR}/
+ @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.la - Parameterized "function" that adds a new rule
+# and phony target for installing a libtool library
+#
+# FIXME: The libtool install *also* installs a bunch of other files.
+# ensure that those are removed, too.
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_RULE.la
+ ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Global install depends on ${1}
+ install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+ # Install libtool library ${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/$${RELINK}${1}
+ @$(ECHO) INSTALL ${1}
+ @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+ @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/lib/$${RELINK}${1} $${${1}_INSTALLDIR}/
+ @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.man - Parameterized "function" that adds a new rule
+# and phony target for installing a "man" page. It will take care of
+# installing it into the correct subdirectory of "man".
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_RULE.man
+ ALL_INSTALL += ${2}/$(notdir ${1})
+
+ # Global install depends on ${1}
+ install: ${2}/$(notdir ${1})
+
+ # Install manual page ${1}
+ ${2}/$(notdir ${1}): ${1} ${2}
+ @$(ECHO) INSTALL ${1}
+ @$${PROGRAM_INSTALL} -c -m 644 ${1} ${2}/
+
+endef
+
+
+# ADD_INSTALL_TARGET - Parameterized "function" that adds a new rule
+# which installs everything for the target.
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_TARGET
+ # Figure out which target rule to use for installation.
+ ifeq "$${${1}_SUFFIX}" ".exe"
+ ifeq "$${TGT_INSTALLDIR}" ".."
+ TGT_INSTALLDIR := $${bindir}
+ endif
+ else
+ ifeq "$${TGT_INSTALLDIR}" ".."
+ TGT_INSTALLDIR := $${libdir}
+ endif
+ endif
+
+ ${1}_INSTALLDIR := ${LL}$${DESTDIR}$${TGT_INSTALLDIR}
+
+ # add rules to install the target
+ ifneq "$${${1}_INSTALLDIR}" ""
+ $$(eval $$(call ADD_INSTALL_RULE$${${1}_SUFFIX},${1}))
+ endif
+
+ # add rules to install the MAN pages.
+ ifneq "$$(strip $${${1}_MAN})" ""
+ ifeq "$${mandir}" ""
+ $$(error You must define 'mandir' in order to be able to install MAN pages.)
+ endif
+
+ MAN := $$(call QUALIFY_PATH,$${DIR},$${MAN})
+ MAN := $$(call CANONICAL_PATH,$${MAN})
+
+ $$(foreach PAGE,$${MAN},\
+ $$(eval $$(call ADD_INSTALL_RULE.man,$${PAGE},\
+ $${DESTDIR}$${mandir}/man$$(subst .,,$$(suffix $${PAGE})))))
+ endif
+endef
+
+.PHONY: install
+install:
+
+ALL_INSTALL :=
+
+# Define reasonable defaults for all of the installation directories.
+# The user can over-ride these, but these are the defaults.
+ifeq "${prefix}" ""
+ prefix = /usr/local
+endif
+ifeq "${exec_prefix}" ""
+ exec_prefix = ${prefix}
+endif
+ifeq "${bindir}" ""
+ bindir = ${exec_prefix}/bin
+endif
+ifeq "${sbindir}" ""
+ sbindir = ${exec_prefix}/sbin
+endif
+ifeq "${libdir}" ""
+ libdir = ${exec_prefix}/lib
+endif
+ifeq "${sysconfdir}" ""
+ sysconfdir = ${prefix}/etc
+endif
+ifeq "${localstatedir}" ""
+ localstatedir = ${prefix}/var
+endif
+ifeq "${datarootdir}" ""
+ datarootdir = ${prefix}/share
+endif
+ifeq "${datadir}" ""
+ datadir = ${prefix}/share
+endif
+ifeq "${mandir}" ""
+ mandir = ${datadir}/man
+endif
+ifeq "${docdir}" ""
+ ifneq "${PROJECT_NAME}" ""
+ docdir = ${datadir}/doc/${PROJECT_NAME}
+ endif
+endif
+ifeq "${logdir}" ""
+ logdir = ${localstatedir}/log/
+endif
+ifeq "${includedir}" ""
+ includedir = ${prefix}/include
+endif
+
+
+# Un-install any installed programs. We DON'T want to depend on the
+# install target. Doing so would cause "make uninstall" to build it,
+# install it, and then remove it.
+#
+# We also want to uninstall only when there are "install_foo" targets.
+.PHONY: uninstall
+uninstall:
+ @rm -f ${ALL_INSTALL} ./.no_such_file
+
+# Wrapper around INSTALL
+ifeq "${PROGRAM_INSTALL}" ""
+ PROGRAM_INSTALL := ${INSTALL}
+
+endif
+
+# Make just the installation directories
+.PHONY: installdirs
+installdirs:
+
+# Be nice to the user. If there is no INSTALL program, then print out
+# a helpful message. Without this check, the "install" rules defined
+# above would try to run a command-line with a blank INSTALL, and give
+# some inscrutable error.
+ifeq "${INSTALL}" ""
+install: install_ERROR
+
+.PHONY: install_ERROR
+install_ERROR:
+ @$(ECHO) Please define INSTALL in order to enable the installation rules.
+ @exit 1
+endif
--- /dev/null
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if !defined(__MINGW32__)
+#include <sys/wait.h>
+#endif
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifdef __EMX__
+# define SHELL_CMD "sh"
+# define GEN_EXPORTS "emxexp"
+# define DEF2IMPLIB_CMD "emximp"
+# define SHARE_SW "-Zdll -Zmtd"
+# define USE_OMF 1
+# define TRUNCATE_DLL_NAME
+# define DYNAMIC_LIB_EXT "dll"
+# define EXE_EXT ".exe"
+
+# if USE_OMF
+ /* OMF is the native format under OS/2 */
+# define STATIC_LIB_EXT "lib"
+# define OBJECT_EXT "obj"
+# define LIBRARIAN "emxomfar"
+# define LIBRARIAN_OPTS "cr"
+# else
+ /* but the alternative, a.out, can fork() which is sometimes necessary */
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# endif
+#endif
+
+#if defined(__APPLE__)
+# define SHELL_CMD "/bin/sh"
+# define DYNAMIC_LIB_EXT "dylib"
+# define MODULE_LIB_EXT "bundle"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+/* man libtool(1) documents ranlib option of -c. */
+# define RANLIB "ranlib"
+# define PIC_FLAG "-fPIC -fno-common"
+# define SHARED_OPTS "-dynamiclib"
+# define MODULE_OPTS "-bundle -dynamic"
+# define DYNAMIC_LINK_OPTS "-flat_namespace"
+# define DYNAMIC_LINK_UNDEFINED "-undefined suppress"
+# define dynamic_link_version_func darwin_dynamic_link_function
+# define DYNAMIC_INSTALL_NAME "-install_name"
+# define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
+# define HAS_REALPATH
+/*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
+# define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
+# define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH"
+#endif
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+# define SHELL_CMD "/bin/sh"
+# define DYNAMIC_LIB_EXT "so"
+# define MODULE_LIB_EXT "so"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# define RANLIB "ranlib"
+# define PIC_FLAG "-fPIC"
+# define RPATH "-rpath"
+# define SHARED_OPTS "-shared"
+# define MODULE_OPTS "-shared"
+# define DYNAMIC_LINK_OPTS "-export-dynamic"
+# define LINKER_FLAG_PREFIX "-Wl,"
+# define ADD_MINUS_L
+# define LD_RUN_PATH "LD_RUN_PATH"
+# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+# define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(sun)
+# define SHELL_CMD "/bin/sh"
+# define DYNAMIC_LIB_EXT "so"
+# define MODULE_LIB_EXT "so"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# define RANLIB "ranlib"
+# define PIC_FLAG "-KPIC"
+# define RPATH "-R"
+# define SHARED_OPTS "-G"
+# define MODULE_OPTS "-G"
+# define DYNAMIC_LINK_OPTS ""
+# define LINKER_FLAG_NO_EQUALS
+# define ADD_MINUS_L
+# define HAS_REALPATH
+# define LD_RUN_PATH "LD_RUN_PATH"
+# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+# define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(_OSD_POSIX)
+# define SHELL_CMD "/usr/bin/sh"
+# define DYNAMIC_LIB_EXT "so"
+# define MODULE_LIB_EXT "so"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# define SHARED_OPTS "-G"
+# define MODULE_OPTS "-G"
+# define LINKER_FLAG_PREFIX "-Wl,"
+# define NEED_SNPRINTF
+#endif
+
+#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
+# define SHELL_CMD "/usr/bin/sh"
+# define DYNAMIC_LIB_EXT "so"
+# define MODULE_LIB_EXT "so"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# define RPATH "-Brpath"
+# define SHARED_OPTS "-G"
+# define MODULE_OPTS "-G"
+# define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
+# define LINKER_FLAG_PREFIX "-Wl,"
+# define NEED_SNPRINTF
+# define LD_RUN_PATH "LD_RUN_PATH"
+# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+# define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(__MINGW32__)
+# define SHELL_CMD "sh"
+# define DYNAMIC_LIB_EXT "dll"
+# define MODULE_LIB_EXT "dll"
+# define STATIC_LIB_EXT "a"
+# define OBJECT_EXT "o"
+# define LIBRARIAN "ar"
+# define LIBRARIAN_OPTS "cr"
+# define RANLIB "ranlib"
+# define LINKER_FLAG_PREFIX "-Wl,"
+# define SHARED_OPTS "-shared"
+# define MODULE_OPTS "-shared"
+# define MKDIR_NO_UMASK
+# define EXE_EXT ".exe"
+#endif
+
+#define OBJDIR ".libs"
+
+#ifndef SHELL_CMD
+#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
+#endif
+
+#ifdef NEED_SNPRINTF
+#include <stdarg.h>
+#endif
+
+#ifdef __EMX__
+#include <process.h>
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+
+/* We want to say we are libtool 1.4 for shlibtool compatibility. */
+#define VERSION "1.4"
+
+enum tool_mode_t {
+ mUnknown,
+ mCompile,
+ mLink,
+ mExecute,
+ mInstall,
+};
+
+enum output_t {
+ otGeneral,
+ otObject,
+ otProgram,
+ otLibrary,
+ otStaticLibraryOnly,
+ otDynamicLibraryOnly,
+ otModule,
+};
+
+enum pic_mode_e {
+ pic_UNKNOWN,
+ pic_PREFER,
+ pic_AVOID,
+};
+
+enum shared_mode_e {
+ share_UNSET,
+ share_STATIC,
+ share_SHARED,
+};
+
+enum lib_type {
+ type_UNKNOWN,
+ type_DYNAMIC_LIB,
+ type_STATIC_LIB,
+ type_MODULE_LIB,
+ type_OBJECT,
+};
+
+typedef struct {
+ const char **vals;
+ int num;
+} count_chars;
+
+typedef struct {
+ const char *normal;
+ const char *install;
+} library_name;
+
+typedef struct {
+ count_chars *normal;
+ count_chars *install;
+ count_chars *dependencies;
+} library_opts;
+
+typedef struct {
+ int silent;
+ int debug;
+ enum shared_mode_e shared;
+ int export_all;
+ int dry_run;
+ enum pic_mode_e pic_mode;
+ int export_dynamic;
+ int no_install;
+} options_t;
+
+typedef struct {
+ enum tool_mode_t mode;
+ enum output_t output;
+ options_t options;
+
+ char *output_name;
+ char *fake_output_name;
+ char *basename;
+
+ const char *install_path;
+ const char *compiler;
+ const char *program;
+ count_chars *program_opts;
+
+ count_chars *arglist;
+ count_chars *tmp_dirs;
+ count_chars *obj_files;
+ count_chars *dep_rpaths;
+ count_chars *rpaths;
+
+ library_name static_name;
+ library_name shared_name;
+ library_name module_name;
+
+ library_opts static_opts;
+ library_opts shared_opts;
+
+ const char *version_info;
+ const char *undefined_flag;
+} command_t;
+
+#ifdef RPATH
+static void add_rpath(count_chars *cc, const char *path);
+#endif
+
+static void usage(int code)
+{
+ printf("Usage: jlibtool [OPTIONS...] COMMANDS...\n");
+ printf("jlibtool is a replacement for GNU libtool with similar functionality.\n\n");
+
+ printf(" --config show all configuration variables\n");
+ printf(" --debug enable verbose shell tracing\n");
+ printf(" --dry-run display commands without modifying any files\n");
+ printf(" --help display this help message and exit\n");
+ printf(" --mode=MODE use operational mode MODE (you *must* set mode)\n");
+
+ printf(" --silent don't print informational messages\n");
+ printf(" --tag=TAG Ignored for libtool compatibility\n");
+ printf(" --version print version information\n");
+
+
+ printf(" --shared Build shared libraries when using --mode=link\n");
+ printf(" --export-all Try to export 'def' file on some platforms\n");
+
+ printf("\nMODE must be one of the following:\n\n");
+ printf(" compile compile a source file into a jlibtool object\n");
+ printf(" execute automatically set library path, then run a program\n");
+ printf(" install install libraries or executables\n");
+ printf(" link create a library or an executable\n");
+
+ printf("\nMODE-ARGS can be the following:\n\n");
+ printf(" -export-dynamic accepted and ignored\n");
+ printf(" -module create a module when linking\n");
+ printf(" -shared create a shared library when linking\n");
+ printf(" -prefer-pic prefer position-independent-code when compiling\n");
+ printf(" -prefer-non-pic prefer non position-independent-code when compiling\n");
+ printf(" -static create a static library when linking\n");
+ printf(" -no-install link libraries locally\n");
+ printf(" -l arg pass '-l arg' to the link stage\n");
+ printf(" -L arg pass '-L arg' to the link stage\n");
+ printf(" -R dir add 'dir' to runtime library search path.\n");
+ printf(" -Zexe accepted and ignored\n");
+ printf(" -avoid-version accepted and ignored\n");
+
+ exit(code);
+}
+
+#if defined(NEED_SNPRINTF)
+/* Write at most n characters to the buffer in str, return the
+ * number of chars written or -1 if the buffer would have been
+ * overflowed.
+ *
+ * This is portable to any POSIX-compliant system has /dev/null
+ */
+static FILE *f=NULL;
+static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+ int res;
+
+ if (f == NULL)
+ f = fopen("/dev/null","w");
+ if (f == NULL)
+ return -1;
+
+ setvbuf( f, str, _IOFBF, n );
+
+ res = vfprintf( f, fmt, ap );
+
+ if ( res > 0 && res < n ) {
+ res = vsprintf( str, fmt, ap );
+ }
+ return res;
+}
+static int snprintf( char *str, size_t n, const char *fmt, ... )
+{
+ va_list ap;
+ int res;
+
+ va_start( ap, fmt );
+ res = vsnprintf( str, n, fmt, ap );
+ va_end( ap );
+ return res;
+}
+#endif
+
+static void init_count_chars(count_chars *cc)
+{
+ cc->vals = (const char**)malloc(PATH_MAX*sizeof(char*));
+ cc->num = 0;
+}
+
+static void clear_count_chars(count_chars *cc)
+{
+ int i;
+ for (i = 0; i < cc->num; i++) {
+ cc->vals[i] = 0;
+ }
+
+ cc->num = 0;
+}
+
+static void push_count_chars(count_chars *cc, const char *newval)
+{
+ cc->vals[cc->num++] = newval;
+}
+
+static void pop_count_chars(count_chars *cc)
+{
+ cc->num--;
+}
+
+static void insert_count_chars(count_chars *cc, const char *newval, int position)
+{
+ int i;
+
+ for (i = cc->num; i > position; i--) {
+ cc->vals[i] = cc->vals[i-1];
+ }
+
+ cc->vals[position] = newval;
+ cc->num++;
+}
+
+static void append_count_chars(count_chars *cc, count_chars *cctoadd)
+{
+ int i;
+ for (i = 0; i < cctoadd->num; i++) {
+ if (cctoadd->vals[i]) {
+ push_count_chars(cc, cctoadd->vals[i]);
+ }
+ }
+}
+
+static const char *flatten_count_chars(count_chars *cc, int space)
+{
+ int i, size;
+ char *newval;
+
+ size = 0;
+ for (i = 0; i < cc->num; i++) {
+ if (cc->vals[i]) {
+ size += strlen(cc->vals[i]) + 1;
+ if (space) {
+ size++;
+ }
+ }
+ }
+
+ newval = (char*)malloc(size + 1);
+ newval[0] = 0;
+
+ for (i = 0; i < cc->num; i++) {
+ if (cc->vals[i]) {
+ strcat(newval, cc->vals[i]);
+ if (space) {
+ strcat(newval, " ");
+ }
+ }
+ }
+
+ return newval;
+}
+
+static char *shell_esc(const char *str)
+{
+ int in_quote = 0;
+ char *cmd;
+ unsigned char *d;
+ const unsigned char *s;
+
+ cmd = (char *)malloc(2 * strlen(str) + 3);
+ d = (unsigned char *)cmd;
+ s = (const unsigned char *)str;
+
+#ifdef __MINGW32__
+ *d++ = '\"';
+#endif
+
+ for (; *s; ++s) {
+ if (*s == '"') {
+ *d++ = '\\';
+ in_quote++;
+ }
+ else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
+ *d++ = '\\';
+ }
+ *d++ = *s;
+ }
+
+#ifdef __MINGW32__
+ *d++ = '\"';
+#endif
+
+ *d = '\0';
+ return cmd;
+}
+
+static int external_spawn(command_t *cmd, const char *file, const char **argv)
+{
+ if (!cmd->options.silent) {
+ const char **argument = argv;
+ // printf("Executing: ");
+ while (*argument) {
+ printf("%s ", *argument);
+ argument++;
+ }
+ puts("");
+ }
+
+ if (cmd->options.dry_run) {
+ return 0;
+ }
+#if defined(__EMX__) || defined(__MINGW32__)
+ return spawnvp(P_WAIT, argv[0], argv);
+#else
+ {
+ pid_t pid;
+ pid = fork();
+ if (pid == 0) {
+ return execvp(argv[0], (char**)argv);
+ }
+ else {
+ int statuscode;
+ waitpid(pid, &statuscode, 0);
+ if (WIFEXITED(statuscode)) {
+ return WEXITSTATUS(statuscode);
+ }
+ return 0;
+ }
+ }
+#endif
+}
+
+static int run_command(command_t *cmd_data, count_chars *cc)
+{
+ char *command;
+ const char *spawn_args[4];
+ count_chars tmpcc;
+
+ init_count_chars(&tmpcc);
+
+ if (cmd_data->program) {
+ push_count_chars(&tmpcc, cmd_data->program);
+ }
+
+ append_count_chars(&tmpcc, cmd_data->program_opts);
+
+ append_count_chars(&tmpcc, cc);
+
+ command = shell_esc(flatten_count_chars(&tmpcc, 1));
+
+ spawn_args[0] = SHELL_CMD;
+ spawn_args[1] = "-c";
+ spawn_args[2] = command;
+ spawn_args[3] = NULL;
+
+ return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
+}
+
+/*
+ * print configuration
+ * shlibpath_var is used in configure.
+ */
+#define printc(_x,_y) printf(_x "=\"%s\"\n", _y)
+
+static void print_config(void)
+{
+#ifdef LD_RUN_PATH
+ printc("runpath_var", LD_RUN_PATH);
+#endif
+#ifdef LD_LIBRARY_PATH
+ printc("shlibpath_var", LD_LIBRARY_PATH);
+#endif
+#ifdef LD_LIBRARY_PATH_LOCAL
+ printc("shlocallibpath_var", LD_LIBRARY_PATH_LOCAL);
+#endif
+#ifdef SHELL_CMD
+ printc("SHELL", SHELL_CMD);
+#endif
+#ifdef OBJECT_EXT
+ printc("objext", OBJECT_EXT);
+#endif
+#ifdef OBJDIR
+ printc("objdir", OBJDIR);
+#endif
+#ifdef DYNAMIC_LIB_EXT
+ /* add a '.' prefix because libtool does that. */
+ printc("shrext_cmds", "echo ." DYNAMIC_LIB_EXT);
+ /* add a '.' prefix because libtool does that. */
+ printc("shrext", "." DYNAMIC_LIB_EXT);
+#endif
+#ifdef EXE_EXT
+ printc("exeext", EXE_EXT);
+#endif
+#ifdef STATIC_LIB_EXT
+ printc("libext", STATIC_LIB_EXT);
+#endif
+#ifdef LIBRARIAN
+ printc("AR", LIBRARIAN);
+#endif
+#ifdef LIBRARIAN_OPTS
+ printc("AR_FLAGS", LIBRARIAN_OPTS);
+#endif
+#ifdef LINKER_FLAG_PREFIX
+ printc("wl", LINKER_FLAG_PREFIX);
+#endif
+#ifdef RANLIB
+ printc("ranlib", RANLIB);
+#endif
+}
+/*
+ * Add a directory to the runtime library search path.
+ */
+static void add_runtimedirlib(char *arg, command_t *cmd_data)
+{
+#ifdef RPATH
+ add_rpath(cmd_data->shared_opts.dependencies, arg);
+#else
+#endif
+}
+
+static int parse_long_opt(char *arg, command_t *cmd_data)
+{
+ char *equal_pos = strchr(arg, '=');
+ char var[50];
+ char value[500];
+
+ if (equal_pos) {
+ strncpy(var, arg, equal_pos - arg);
+ var[equal_pos - arg] = 0;
+ strcpy(value, equal_pos + 1);
+ } else {
+ strcpy(var, arg);
+ }
+
+ if (strcmp(var, "silent") == 0) {
+ cmd_data->options.silent = 1;
+ } else if (strcmp(var, "debug") == 0) {
+ cmd_data->options.debug = 1;
+ } else if (strcmp(var, "mode") == 0) {
+ if (strcmp(value, "compile") == 0) {
+ cmd_data->mode = mCompile;
+ cmd_data->output = otObject;
+
+ } else if (strcmp(value, "link") == 0) {
+ cmd_data->mode = mLink;
+ cmd_data->output = otLibrary;
+
+ } else if (strcmp(value, "install") == 0) {
+ cmd_data->mode = mInstall;
+
+ } else if (strcmp(value, "execute") == 0) {
+ cmd_data->mode = mExecute;
+
+ } else {
+ printf("Unknown mode \"%s\"\n", value);
+ }
+ } else if (strcmp(var, "shared") == 0) {
+ if ((cmd_data->mode == mLink) &&
+ (cmd_data->output == otGeneral)) {
+ cmd_data->output = otDynamicLibraryOnly;
+ }
+ cmd_data->options.shared = share_SHARED;
+ } else if (strcmp(var, "export-all") == 0) {
+ cmd_data->options.export_all = 1;
+ } else if (strcmp(var, "dry-run") == 0) {
+ printf("Dry-run mode on!\n");
+ cmd_data->options.dry_run = 1;
+ } else if (strcmp(var, "version") == 0) {
+ printf("Version " VERSION "\n");
+ } else if (strcmp(var, "help") == 0) {
+ usage(0);
+ } else if (strcmp(var, "config") == 0) {
+ print_config();
+ } else if (strcmp(var, "tag") == 0) {
+ if (strcmp(value, "CC") == 0) {
+ /* Do nothing. */
+ }
+ if (strcmp(value, "CXX") == 0) {
+ /* Do nothing. */
+ }
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return 1 if we eat it. */
+static int parse_short_opt(char *arg, command_t *cmd_data)
+{
+ if (strcmp(arg, "export-dynamic") == 0) {
+ cmd_data->options.export_dynamic = 1;
+ return 1;
+ }
+
+ if (strcmp(arg, "module") == 0) {
+ cmd_data->output = otModule;
+ return 1;
+ }
+
+ if (strcmp(arg, "shared") == 0) {
+ if (cmd_data->mode == mLink) {
+ cmd_data->output = otDynamicLibraryOnly;
+ }
+ cmd_data->options.shared = share_SHARED;
+ return 1;
+ }
+
+ if (strcmp(arg, "Zexe") == 0) {
+ return 1;
+ }
+
+ if (strcmp(arg, "avoid-version") == 0) {
+ return 1;
+ }
+
+ if (strcmp(arg, "prefer-pic") == 0) {
+ cmd_data->options.pic_mode = pic_PREFER;
+ return 1;
+ }
+
+ if (strcmp(arg, "prefer-non-pic") == 0) {
+ cmd_data->options.pic_mode = pic_AVOID;
+ return 1;
+ }
+
+ if (strcmp(arg, "static") == 0) {
+ cmd_data->options.shared = share_STATIC;
+ return 1;
+ }
+
+ if (cmd_data->mode == mLink) {
+ if (strcmp(arg, "no-install") == 0) {
+ cmd_data->options.no_install = 1;
+ return 1;
+ }
+ if (arg[0] == 'L' || arg[0] == 'l') {
+ /* Hack... */
+ arg--;
+ push_count_chars(cmd_data->shared_opts.dependencies, arg);
+ return 1;
+ } else if (arg[0] == 'R' && arg[1]) {
+ /* -Rdir Add dir to runtime library search path. */
+ add_runtimedirlib(&arg[1], cmd_data);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static char *truncate_dll_name(char *path)
+{
+ /* Cut DLL name down to 8 characters after removing any mod_ prefix */
+ char *tmppath = strdup(path);
+ char *newname = strrchr(tmppath, '/') + 1;
+ char *ext = strrchr(newname, '.');
+ int len;
+
+ if (ext == NULL)
+ return tmppath;
+
+ len = ext - newname;
+
+ if (strncmp(newname, "mod_", 4) == 0) {
+ strcpy(newname, newname + 4);
+ len -= 4;
+ }
+
+ if (len > 8) {
+ strcpy(newname + 8, strchr(newname, '.'));
+ }
+
+ return tmppath;
+}
+
+static long safe_strtol(const char *nptr, const char **endptr, int base)
+{
+ long rv;
+
+ errno = 0;
+
+ rv = strtol(nptr, (char**)endptr, 10);
+
+ if (errno == ERANGE) {
+ return 0;
+ }
+
+ return rv;
+}
+
+static void safe_mkdir(const char *path)
+{
+ mode_t old_umask;
+
+ old_umask = umask(0);
+ umask(old_umask);
+
+#ifdef MKDIR_NO_UMASK
+ mkdir(path);
+#else
+ mkdir(path, ~old_umask);
+#endif
+}
+
+/* returns just a file's name without the path */
+static const char *jlibtool_basename(const char *fullpath)
+{
+ const char *name = strrchr(fullpath, '/');
+
+ if (name == NULL) {
+ name = strrchr(fullpath, '\\');
+ }
+
+ if (name == NULL) {
+ name = fullpath;
+ } else {
+ name++;
+ }
+
+ return name;
+}
+
+/* returns just a file's name without path or extension */
+static const char *nameof(const char *fullpath)
+{
+ const char *name;
+ const char *ext;
+
+ name = jlibtool_basename(fullpath);
+ ext = strrchr(name, '.');
+
+ if (ext) {
+ char *trimmed;
+ trimmed = malloc(ext - name + 1);
+ strncpy(trimmed, name, ext - name);
+ trimmed[ext-name] = 0;
+ return trimmed;
+ }
+
+ return name;
+}
+
+/* version_info is in the form of MAJOR:MINOR:PATCH */
+static const char *darwin_dynamic_link_function(const char *version_info)
+{
+ char *newarg;
+ long major, minor, patch;
+
+ major = 0;
+ minor = 0;
+ patch = 0;
+
+ if (version_info) {
+ major = safe_strtol(version_info, &version_info, 10);
+
+ if (version_info) {
+ if (version_info[0] == ':') {
+ version_info++;
+ }
+
+ minor = safe_strtol(version_info, &version_info, 10);
+
+ if (version_info) {
+ if (version_info[0] == ':') {
+ version_info++;
+ }
+
+ patch = safe_strtol(version_info, &version_info, 10);
+
+ }
+ }
+ }
+
+ /* Avoid -dylib_compatibility_version must be greater than zero errors. */
+ if (major == 0) {
+ major = 1;
+ }
+ newarg = (char*)malloc(100);
+ snprintf(newarg, 99,
+ "-compatibility_version %ld -current_version %ld.%ld",
+ major, major, minor);
+
+ return newarg;
+}
+
+
+/*
+ * Add a '.libs/' to the buffer. The caller ensures that
+ * The buffer is large enough to handle 6 extra characters.
+ */
+static void add_dotlibs(char *buffer)
+{
+ char *name = strrchr(buffer, '/');
+
+ if (!name) {
+ if (!buffer[0]) {
+ strcpy(buffer, ".libs/");
+ return;
+ }
+ name = buffer;
+ } else {
+ name++;
+ }
+ memmove(name + 6, name, strlen(name));
+ memcpy(name, ".libs/", 6);
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+static char *gen_library_name(const char *name, int genlib)
+{
+ char *newarg, *newext;
+
+ newarg = (char *)malloc(strlen(name) + 11);
+
+ if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
+ name += 3;
+ }
+
+ if (genlib == 2) {
+ strcat(newarg, jlibtool_basename(name));
+ }
+ else {
+ strcat(newarg, name);
+ }
+
+ newext = strrchr(newarg, '.') + 1;
+
+ switch (genlib) {
+ case 0:
+ strcpy(newext, STATIC_LIB_EXT);
+ break;
+ case 1:
+ strcpy(newext, DYNAMIC_LIB_EXT);
+ break;
+ case 2:
+ strcpy(newext, MODULE_LIB_EXT);
+ break;
+ }
+
+ add_dotlibs(newarg);
+
+ return newarg;
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+static char *gen_install_name(const char *name, int genlib)
+{
+ struct stat sb;
+ char *newname;
+ int rv;
+
+ newname = gen_library_name(name, genlib);
+
+ /* Check if it exists. If not, return NULL. */
+ rv = stat(newname, &sb);
+
+ if (rv) {
+ return NULL;
+ }
+
+ return newname;
+}
+
+static char *check_object_exists(command_t *cmd, const char *arg, int arglen)
+{
+ char *newarg, *ext;
+ int pass, rv;
+
+ newarg = (char *)malloc(arglen + 10);
+ memcpy(newarg, arg, arglen);
+ newarg[arglen] = 0;
+ ext = newarg + arglen;
+
+ pass = 0;
+
+ do {
+ struct stat sb;
+
+ switch (pass) {
+ case 0:
+ strcpy(ext, OBJECT_EXT);
+ break;
+/*
+ case 1:
+ strcpy(ext, NO_PIC_EXT);
+ break;
+*/
+ default:
+ break;
+ }
+
+ if (cmd->options.debug) {
+ printf("Checking (obj): %s\n", newarg);
+ }
+ rv = stat(newarg, &sb);
+ }
+ while (rv != 0 && ++pass < 1);
+
+ if (rv == 0) {
+ if (pass == 1) {
+ cmd->options.pic_mode = pic_AVOID;
+ }
+ return newarg;
+ }
+
+ return NULL;
+}
+
+/* libdircheck values:
+ * 0 - no .libs suffix
+ * 1 - .libs suffix
+ */
+static char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
+ int libdircheck, enum lib_type *libtype)
+{
+ char *newarg, *ext;
+ int pass, rv, newpathlen;
+
+ newarg = (char *)malloc(strlen(arg) + 10);
+ strcpy(newarg, arg);
+ newarg[pathlen] = 0;
+
+ newpathlen = pathlen;
+ if (libdircheck) {
+ add_dotlibs(newarg);
+ newpathlen += sizeof(".libs/") - 1;
+ }
+
+ strcpy(newarg+newpathlen, arg+pathlen);
+ ext = strrchr(newarg, '.') + 1;
+
+ pass = 0;
+
+ do {
+ struct stat sb;
+
+ switch (pass) {
+ case 0:
+ if (cmd->options.pic_mode != pic_AVOID &&
+ cmd->options.shared != share_STATIC) {
+ strcpy(ext, DYNAMIC_LIB_EXT);
+ *libtype = type_DYNAMIC_LIB;
+ break;
+ }
+ pass = 1;
+ /* Fall through */
+ case 1:
+ strcpy(ext, STATIC_LIB_EXT);
+ *libtype = type_STATIC_LIB;
+ break;
+ case 2:
+ strcpy(ext, MODULE_LIB_EXT);
+ *libtype = type_MODULE_LIB;
+ break;
+ case 3:
+ strcpy(ext, OBJECT_EXT);
+ *libtype = type_OBJECT;
+ break;
+ default:
+ *libtype = type_UNKNOWN;
+ break;
+ }
+
+ if (cmd->options.debug) {
+ printf("Checking (lib): %s\n", newarg);
+ }
+ rv = stat(newarg, &sb);
+ }
+ while (rv != 0 && ++pass < 4);
+
+ if (rv == 0) {
+ return newarg;
+ }
+
+ return NULL;
+}
+
+static char * load_install_path(const char *arg)
+{
+ FILE *f;
+ char *path;
+
+ path = malloc(PATH_MAX);
+
+ f = fopen(arg,"r");
+ if (f == NULL) {
+ return NULL;
+ }
+ fgets(path, PATH_MAX, f);
+ fclose(f);
+ if (path[strlen(path)-1] == '\n') {
+ path[strlen(path)-1] = '\0';
+ }
+ /* Check that we have an absolute path.
+ * Otherwise the file could be a GNU libtool file.
+ */
+ if (path[0] != '/') {
+ return NULL;
+ }
+ return path;
+}
+
+static char * load_noinstall_path(const char *arg, int pathlen)
+{
+ char *newarg, *expanded_path;
+ int newpathlen;
+
+ newarg = (char *)malloc(strlen(arg) + 10);
+ strcpy(newarg, arg);
+ newarg[pathlen] = 0;
+
+ newpathlen = pathlen;
+ strcat(newarg, ".libs");
+ newpathlen += sizeof(".libs") - 1;
+ newarg[newpathlen] = 0;
+
+#ifdef HAS_REALPATH
+ expanded_path = malloc(PATH_MAX);
+ expanded_path = realpath(newarg, expanded_path);
+ /* Uh, oh. There was an error. Fall back on our first guess. */
+ if (!expanded_path) {
+ expanded_path = newarg;
+ }
+#else
+ /* We might get ../ or something goofy. Oh, well. */
+ expanded_path = newarg;
+#endif
+
+ return expanded_path;
+}
+
+static void add_dynamic_link_opts(command_t *cmd_data, count_chars *args)
+{
+#ifdef DYNAMIC_LINK_OPTS
+ if (cmd_data->options.pic_mode != pic_AVOID) {
+ if (cmd_data->options.debug) {
+ printf("Adding: %s\n", DYNAMIC_LINK_OPTS);
+ }
+ push_count_chars(args, DYNAMIC_LINK_OPTS);
+ if (cmd_data->undefined_flag) {
+ push_count_chars(args, "-undefined");
+#if defined(__APPLE__)
+ /* -undefined dynamic_lookup is used by the bundled Python in
+ * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+,
+ * we'll get a linker error if we pass this flag.
+ */
+ if (strcasecmp(cmd_data->undefined_flag,
+ "dynamic_lookup") == 0) {
+ insert_count_chars(cmd_data->program_opts,
+ "MACOSX_DEPLOYMENT_TARGET=10.3", 0);
+ }
+#endif
+ push_count_chars(args, cmd_data->undefined_flag);
+ }
+ else {
+#ifdef DYNAMIC_LINK_UNDEFINED
+ if (cmd_data->options.debug) {
+ printf("Adding: %s\n", DYNAMIC_LINK_UNDEFINED);
+ }
+ push_count_chars(args, DYNAMIC_LINK_UNDEFINED);
+#endif
+ }
+ }
+#endif
+}
+
+/* Read the final install location and add it to runtime library search path. */
+#ifdef RPATH
+static void add_rpath(count_chars *cc, const char *path)
+{
+ int size = 0;
+ char *tmp;
+
+#ifdef LINKER_FLAG_PREFIX
+ size = strlen(LINKER_FLAG_PREFIX);
+#endif
+ size = size + strlen(path) + strlen(RPATH) + 2;
+ tmp = malloc(size);
+ if (tmp == NULL) {
+ return;
+ }
+#ifdef LINKER_FLAG_PREFIX
+ strcpy(tmp, LINKER_FLAG_PREFIX);
+ strcat(tmp, RPATH);
+#else
+ strcpy(tmp, RPATH);
+#endif
+#ifndef LINKER_FLAG_NO_EQUALS
+ strcat(tmp, "=");
+#endif
+ strcat(tmp, path);
+
+ push_count_chars(cc, tmp);
+}
+
+static void add_rpath_file(count_chars *cc, const char *arg)
+{
+ const char *path;
+
+ path = load_install_path(arg);
+ if (path) {
+ add_rpath(cc, path);
+ }
+}
+
+static void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
+{
+ const char *path;
+
+ path = load_noinstall_path(arg, pathlen);
+ if (path) {
+ add_rpath(cc, path);
+ }
+}
+#endif
+
+#ifdef DYNAMIC_LINK_NO_INSTALL
+static void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
+ int extlen)
+{
+ const char *install_path, *current_path, *name;
+ char *exp_argument;
+ int i_p_len, c_p_len, name_len, dyext_len, cur_len;
+
+ install_path = load_install_path(arg);
+ current_path = load_noinstall_path(arg, pathlen);
+
+ if (!install_path || !current_path) {
+ return;
+ }
+
+ push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
+
+ i_p_len = strlen(install_path);
+ c_p_len = strlen(current_path);
+
+ name = arg+pathlen;
+ name_len = extlen-pathlen;
+ dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
+
+ /* No, we need to replace the extension. */
+ exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
+ (dyext_len*2) + 2);
+
+ cur_len = 0;
+ strcpy(exp_argument, install_path);
+ cur_len += i_p_len;
+ exp_argument[cur_len++] = '/';
+ strncpy(exp_argument+cur_len, name, extlen-pathlen);
+ cur_len += name_len;
+ strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+ cur_len += dyext_len;
+ exp_argument[cur_len++] = ':';
+ strcpy(exp_argument+cur_len, current_path);
+ cur_len += c_p_len;
+ exp_argument[cur_len++] = '/';
+ strncpy(exp_argument+cur_len, name, extlen-pathlen);
+ cur_len += name_len;
+ strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+ cur_len += dyext_len;
+
+ push_count_chars(cc, exp_argument);
+}
+#endif
+
+/* use -L -llibname to allow to use installed libraries */
+static void add_minus_l(count_chars *cc, const char *arg)
+{
+ char *newarg;
+ char *name = strrchr(arg, '/');
+ char *file = strrchr(arg, '.');
+ char *lib = strstr(name, "lib");
+
+ if (name !=NULL && file != NULL && lib == name+1) {
+ *name = '\0';
+ *file = '\0';
+ file = name;
+ file = file+4;
+ push_count_chars(cc, "-L");
+ push_count_chars(cc, arg);
+ /* we need one argument like -lapr-1 */
+ newarg = malloc(strlen(file) + 3);
+ strcpy(newarg, "-l");
+ strcat(newarg, file);
+ push_count_chars(cc, newarg);
+ } else {
+ push_count_chars(cc, arg);
+ }
+}
+
+static void add_linker_flag_prefix(count_chars *cc, const char *arg)
+{
+#ifndef LINKER_FLAG_PREFIX
+ push_count_chars(cc, arg);
+#else
+ char *newarg;
+ newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
+ strcpy(newarg, LINKER_FLAG_PREFIX);
+ strcat(newarg, arg);
+ push_count_chars(cc, newarg);
+#endif
+}
+
+static int explode_static_lib(command_t *cmd_data, const char *lib)
+{
+ count_chars tmpdir_cc, libname_cc;
+ const char *tmpdir, *libname;
+ char savewd[PATH_MAX];
+ const char *name;
+ DIR *dir;
+ struct dirent *entry;
+ const char *lib_args[4];
+
+ /* Bah! */
+ if (cmd_data->options.dry_run) {
+ return 0;
+ }
+
+ name = jlibtool_basename(lib);
+
+ init_count_chars(&tmpdir_cc);
+ push_count_chars(&tmpdir_cc, ".libs/");
+ push_count_chars(&tmpdir_cc, name);
+ push_count_chars(&tmpdir_cc, ".exploded/");
+ tmpdir = flatten_count_chars(&tmpdir_cc, 0);
+
+ if (!cmd_data->options.silent) {
+ printf("Making: %s\n", tmpdir);
+ }
+ safe_mkdir(tmpdir);
+
+ push_count_chars(cmd_data->tmp_dirs, tmpdir);
+
+ getcwd(savewd, sizeof(savewd));
+
+ if (chdir(tmpdir) != 0) {
+ if (!cmd_data->options.silent) {
+ printf("Warning: could not explode %s\n", lib);
+ }
+ return 1;
+ }
+
+ if (lib[0] == '/') {
+ libname = lib;
+ }
+ else {
+ init_count_chars(&libname_cc);
+ push_count_chars(&libname_cc, "../../");
+ push_count_chars(&libname_cc, lib);
+ libname = flatten_count_chars(&libname_cc, 0);
+ }
+
+ lib_args[0] = LIBRARIAN;
+ lib_args[1] = "x";
+ lib_args[2] = libname;
+ lib_args[3] = NULL;
+
+ external_spawn(cmd_data, LIBRARIAN, lib_args);
+
+ chdir(savewd);
+ dir = opendir(tmpdir);
+
+ while ((entry = readdir(dir)) != NULL) {
+#if defined(__APPLE__) && defined(RANLIB)
+ /* Apple inserts __.SYMDEF which isn't needed.
+ * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't
+ * much fun either. Just skip them.
+ */
+ if (strstr(entry->d_name, "__.SYMDEF") != NULL) {
+ continue;
+ }
+#endif
+ if (entry->d_name[0] != '.') {
+ push_count_chars(&tmpdir_cc, entry->d_name);
+ name = flatten_count_chars(&tmpdir_cc, 0);
+ if (cmd_data->options.debug) {
+ printf("Adding: %s\n", name);
+ }
+ push_count_chars(cmd_data->obj_files, name);
+ pop_count_chars(&tmpdir_cc);
+ }
+ }
+
+ closedir(dir);
+ return 0;
+}
+
+static int parse_input_file_name(char *arg, command_t *cmd_data)
+{
+ char *ext = strrchr(arg, '.');
+ const char *name;
+ int pathlen;
+ enum lib_type libtype;
+ char *newarg;
+
+ if (!ext) {
+ return 0;
+ }
+
+ ext++;
+ name = jlibtool_basename(arg);
+
+ pathlen = name - arg;
+
+ if (strcmp(ext, "lo") == 0) {
+ newarg = check_object_exists(cmd_data, arg, ext - arg);
+ if (!newarg) {
+ printf("Can not find suitable object file for %s\n", arg);
+ exit(1);
+ }
+ if (cmd_data->mode != mLink) {
+ push_count_chars(cmd_data->arglist, newarg);
+ }
+ else {
+ push_count_chars(cmd_data->obj_files, newarg);
+ }
+ return 1;
+ }
+
+ if (strcmp(ext, "la") == 0) {
+ switch (cmd_data->mode) {
+ case mLink:
+ /* Try the .libs dir first! */
+ newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
+ if (!newarg) {
+ /* Try the normal dir next. */
+ newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
+ if (!newarg) {
+ printf("Can not find suitable library for %s\n", arg);
+ exit(1);
+ }
+ }
+
+ /* It is not ok to just add the file: a library may added with:
+ 1 - -L path library_name. (For *.so in Linux).
+ 2 - library_name.
+ */
+#ifdef ADD_MINUS_L
+ if (libtype == type_DYNAMIC_LIB) {
+ add_minus_l(cmd_data->shared_opts.dependencies, newarg);
+ } else if (cmd_data->output == otLibrary &&
+ libtype == type_STATIC_LIB) {
+ explode_static_lib(cmd_data, newarg);
+ } else {
+ push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+ }
+#else
+ if (cmd_data->output == otLibrary && libtype == type_STATIC_LIB) {
+ explode_static_lib(cmd_data, newarg);
+ }
+ else {
+ push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+ }
+#endif
+ if (libtype == type_DYNAMIC_LIB) {
+ if (cmd_data->options.no_install) {
+#ifdef RPATH
+ add_rpath_noinstall(cmd_data->shared_opts.dependencies,
+ arg, pathlen);
+#endif
+#ifdef DYNAMIC_LINK_NO_INSTALL
+ /*
+ * This doesn't work as Darwin's linker has no way to
+ * override at link-time the search paths for a
+ * non-installed library.
+ */
+ /*
+ add_dylink_noinstall(cmd_data->shared_opts.dependencies,
+ arg, pathlen, ext - arg);
+ */
+#endif
+ }
+ else {
+#ifdef RPATH
+ add_rpath_file(cmd_data->shared_opts.dependencies, arg);
+#endif
+ }
+ }
+ break;
+ case mInstall:
+ /* If we've already recorded a library to install, we're most
+ * likely getting the .la file that we want to install as.
+ * The problem is that we need to add it as the directory,
+ * not the .la file itself. Otherwise, we'll do odd things.
+ */
+ if (cmd_data->output == otLibrary) {
+ arg[pathlen] = '\0';
+ push_count_chars(cmd_data->arglist, arg);
+ }
+ else {
+ cmd_data->output = otLibrary;
+ cmd_data->output_name = arg;
+ cmd_data->static_name.install = gen_install_name(arg, 0);
+ cmd_data->shared_name.install = gen_install_name(arg, 1);
+ cmd_data->module_name.install = gen_install_name(arg, 2);
+ }
+ break;
+ default:
+ break;
+ }
+ return 1;
+ }
+
+ if (strcmp(ext, "c") == 0) {
+ /* If we don't already have an idea what our output name will be. */
+ if (cmd_data->basename == NULL) {
+ cmd_data->basename = (char *)malloc(strlen(arg) + 4);
+ strcpy(cmd_data->basename, arg);
+ strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
+
+ cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
+ if (cmd_data->fake_output_name) {
+ cmd_data->fake_output_name++;
+ }
+ else {
+ cmd_data->fake_output_name = cmd_data->basename;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int parse_output_file_name(char *arg, command_t *cmd_data)
+{
+ const char *name;
+ char *ext;
+ char *newarg = NULL;
+ int pathlen;
+
+ cmd_data->fake_output_name = arg;
+
+ name = jlibtool_basename(arg);
+ ext = strrchr(name, '.');
+
+#ifdef EXE_EXT
+ if (!ext || strcmp(ext, EXE_EXT) == 0) {
+#else
+ if (!ext) {
+#endif
+ cmd_data->basename = arg;
+ cmd_data->output = otProgram;
+#if defined(_OSD_POSIX)
+ cmd_data->options.pic_mode = pic_AVOID;
+#endif
+ newarg = (char *)malloc(strlen(arg) + 5);
+ strcpy(newarg, arg);
+#ifdef EXE_EXT
+ if (!ext) {
+ strcat(newarg, EXE_EXT);
+ }
+#endif
+ cmd_data->output_name = newarg;
+ return 1;
+ }
+
+ ext++;
+ pathlen = name - arg;
+
+ if (strcmp(ext, "la") == 0) {
+ assert(cmd_data->mode == mLink);
+
+ cmd_data->basename = arg;
+ cmd_data->static_name.normal = gen_library_name(arg, 0);
+ cmd_data->shared_name.normal = gen_library_name(arg, 1);
+ cmd_data->module_name.normal = gen_library_name(arg, 2);
+ cmd_data->static_name.install = gen_install_name(arg, 0);
+ cmd_data->shared_name.install = gen_install_name(arg, 1);
+ cmd_data->module_name.install = gen_install_name(arg, 2);
+
+ if (!cmd_data->options.dry_run) {
+ char *cname;
+
+ cname = malloc(strlen(cmd_data->static_name.normal) + 1);
+
+ strcpy(cname, cmd_data->static_name.normal);
+ ext = strrchr(cname, '/');
+ if (!ext) {
+ /* Check first to see if the dir already exists! */
+ safe_mkdir(".libs");
+ } else {
+ *ext = '\0';
+ safe_mkdir(cname);
+ }
+ free(cname);
+ }
+
+#ifdef TRUNCATE_DLL_NAME
+ if (shared) {
+ arg = truncate_dll_name(arg);
+ }
+#endif
+
+ cmd_data->output_name = arg;
+ return 1;
+ }
+
+ if (strcmp(ext, "lo") == 0) {
+ cmd_data->basename = arg;
+ cmd_data->output = otObject;
+ newarg = (char *)malloc(strlen(arg) + 2);
+ strcpy(newarg, arg);
+ ext = strrchr(newarg, '.') + 1;
+ strcpy(ext, OBJECT_EXT);
+ cmd_data->output_name = newarg;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void parse_args(int argc, char *argv[], command_t *cmd_data)
+{
+ int a;
+ char *arg;
+ int argused;
+
+ for (a = 1; a < argc; a++) {
+ arg = argv[a];
+ argused = 1;
+
+ if (arg[0] == '-') {
+ if (arg[1] == '-') {
+ argused = parse_long_opt(arg + 2, cmd_data);
+ }
+ else {
+ argused = parse_short_opt(arg + 1, cmd_data);
+ }
+
+ /* We haven't done anything with it yet, try some of the
+ * more complicated short opts... */
+ if (argused == 0 && a + 1 < argc) {
+ if (arg[1] == 'o' && !arg[2]) {
+ arg = argv[++a];
+ argused = parse_output_file_name(arg, cmd_data);
+ } else if (strcmp(arg+1, "MT") == 0) {
+ if (cmd_data->options.debug) {
+ printf("Adding: %s\n", arg);
+ }
+ push_count_chars(cmd_data->arglist, arg);
+ arg = argv[++a];
+ if (!cmd_data->options.silent) {
+ printf(" %s\n", arg);
+ }
+ push_count_chars(cmd_data->arglist, arg);
+ argused = 1;
+ } else if (strcmp(arg+1, "rpath") == 0) {
+ /* Aha, we should try to link both! */
+ cmd_data->install_path = argv[++a];
+ argused = 1;
+ } else if (strcmp(arg+1, "release") == 0) {
+ /* Store for later deciphering */
+ cmd_data->version_info = argv[++a];
+ argused = 1;
+ } else if (strcmp(arg+1, "version-info") == 0) {
+ /* Store for later deciphering */
+ cmd_data->version_info = argv[++a];
+ argused = 1;
+ } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
+ /* Skip the argument. */
+ ++a;
+ argused = 1;
+ } else if (strcmp(arg+1, "release") == 0) {
+ /* Skip the argument. */
+ ++a;
+ argused = 1;
+ } else if (strcmp(arg+1, "undefined") == 0) {
+ cmd_data->undefined_flag = argv[++a];
+ argused = 1;
+ } else if (arg[1] == 'R' && !arg[2]) {
+ /* -R dir Add dir to runtime library search path. */
+ add_runtimedirlib(argv[++a], cmd_data);
+ argused = 1;
+ }
+ }
+ } else {
+ argused = parse_input_file_name(arg, cmd_data);
+ }
+
+ if (!argused) {
+ if (cmd_data->options.debug) {
+ printf("Adding: %s\n", arg);
+ }
+ push_count_chars(cmd_data->arglist, arg);
+ }
+ }
+
+}
+
+#ifdef GEN_EXPORTS
+static void generate_def_file(command_t *cmd_data)
+{
+ char def_file[1024];
+ char implib_file[1024];
+ char *ext;
+ FILE *hDef;
+ char *export_args[1024];
+ int num_export_args = 0;
+ char *cmd;
+ int cmd_size = 0;
+ int a;
+
+ if (cmd_data->output_name) {
+ strcpy(def_file, cmd_data->output_name);
+ strcat(def_file, ".def");
+ hDef = fopen(def_file, "w");
+
+ if (hDef != NULL) {
+ fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
+ fprintf(hDef, "DATA NONSHARED\n");
+ fprintf(hDef, "EXPORTS\n");
+ fclose(hDef);
+
+ for (a = 0; a < cmd_data->num_obj_files; a++) {
+ cmd_size += strlen(cmd_data->obj_files[a]) + 1;
+ }
+
+ cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
+ cmd = (char *)malloc(cmd_size);
+ strcpy(cmd, GEN_EXPORTS);
+
+ for (a=0; a < cmd_data->num_obj_files; a++) {
+ strcat(cmd, " ");
+ strcat(cmd, cmd_data->obj_files[a] );
+ }
+
+ strcat(cmd, ">>");
+ strcat(cmd, def_file);
+ puts(cmd);
+ export_args[num_export_args++] = SHELL_CMD;
+ export_args[num_export_args++] = "-c";
+ export_args[num_export_args++] = cmd;
+ export_args[num_export_args++] = NULL;
+ external_spawn(cmd_data, export_args[0], (const char**)export_args);
+ cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
+
+ /* Now make an import library for the dll */
+ num_export_args = 0;
+ export_args[num_export_args++] = DEF2IMPLIB_CMD;
+ export_args[num_export_args++] = "-o";
+
+ strcpy(implib_file, ".libs/");
+ strcat(implib_file, cmd_data->basename);
+ ext = strrchr(implib_file, '.');
+
+ if (ext)
+ *ext = 0;
+
+ strcat(implib_file, ".");
+ strcat(implib_file, STATIC_LIB_EXT);
+
+ export_args[num_export_args++] = implib_file;
+ export_args[num_export_args++] = def_file;
+ export_args[num_export_args++] = NULL;
+ external_spawn(cmd_data, export_args[0], (const char**)export_args);
+
+ }
+ }
+}
+#endif
+
+static const char* expand_path(const char *relpath)
+{
+ char foo[PATH_MAX], *newpath;
+
+ getcwd(foo, PATH_MAX-1);
+ newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
+ strcat(newpath, foo);
+ strcat(newpath, "/");
+ strcat(newpath, relpath);
+ return newpath;
+}
+
+static void link_fixup(command_t *c)
+{
+ /* If we were passed an -rpath directive, we need to build
+ * shared objects too. Otherwise, we should only create static
+ * libraries.
+ */
+ if (!c->install_path && (c->output == otDynamicLibraryOnly ||
+ c->output == otModule || c->output == otLibrary)) {
+ c->output = otStaticLibraryOnly;
+ }
+
+ if (c->output == otDynamicLibraryOnly ||
+ c->output == otModule ||
+ c->output == otLibrary) {
+
+ push_count_chars(c->shared_opts.normal, "-o");
+ if (c->output == otModule) {
+ push_count_chars(c->shared_opts.normal, c->module_name.normal);
+ }
+ else {
+ char *tmp;
+ push_count_chars(c->shared_opts.normal, c->shared_name.normal);
+#ifdef DYNAMIC_INSTALL_NAME
+ push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
+
+ tmp = (char*)malloc(PATH_MAX);
+ strcat(tmp, c->install_path);
+ strcat(tmp, strrchr(c->shared_name.normal, '/'));
+ push_count_chars(c->shared_opts.normal, tmp);
+#endif
+ }
+
+ append_count_chars(c->shared_opts.normal, c->obj_files);
+ append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
+
+ if (c->options.export_all) {
+#ifdef GEN_EXPORTS
+ generate_def_file(c);
+#endif
+ }
+ }
+
+ if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
+ push_count_chars(c->static_opts.normal, "-o");
+ push_count_chars(c->static_opts.normal, c->output_name);
+ }
+
+ if (c->output == otProgram) {
+ if (c->output_name) {
+ push_count_chars(c->arglist, "-o");
+ push_count_chars(c->arglist, c->output_name);
+ append_count_chars(c->arglist, c->obj_files);
+ append_count_chars(c->arglist, c->shared_opts.dependencies);
+ add_dynamic_link_opts(c, c->arglist);
+ }
+ }
+}
+
+static void post_parse_fixup(command_t *cmd_data)
+{
+ switch (cmd_data->mode)
+ {
+ case mCompile:
+#ifdef PIC_FLAG
+ if (cmd_data->options.pic_mode != pic_AVOID) {
+ push_count_chars(cmd_data->arglist, PIC_FLAG);
+ }
+#endif
+ if (cmd_data->output_name) {
+ push_count_chars(cmd_data->arglist, "-o");
+ push_count_chars(cmd_data->arglist, cmd_data->output_name);
+ }
+ break;
+ case mLink:
+ link_fixup(cmd_data);
+ break;
+ case mInstall:
+ if (cmd_data->output == otLibrary) {
+ link_fixup(cmd_data);
+ }
+ default:
+ break;
+ }
+
+#if USE_OMF
+ if (cmd_data->output == otObject ||
+ cmd_data->output == otProgram ||
+ cmd_data->output == otLibrary ||
+ cmd_data->output == otDynamicLibraryOnly) {
+ push_count_chars(cmd_data->arglist, "-Zomf");
+ }
+#endif
+
+ if (cmd_data->options.shared &&
+ (cmd_data->output == otObject ||
+ cmd_data->output == otLibrary ||
+ cmd_data->output == otDynamicLibraryOnly)) {
+#ifdef SHARE_SW
+ push_count_chars(cmd_data->arglist, SHARE_SW);
+#endif
+ }
+}
+
+static int run_mode(command_t *cmd_data)
+{
+ int rv;
+ count_chars *cctemp;
+
+ cctemp = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cctemp);
+
+ switch (cmd_data->mode)
+ {
+ case mCompile:
+ rv = run_command(cmd_data, cmd_data->arglist);
+ if (rv) {
+ return rv;
+ }
+ break;
+ case mInstall:
+ /* Well, we'll assume it's a file going to a directory... */
+ /* For brain-dead install-sh based scripts, we have to repeat
+ * the command N-times. install-sh should die.
+ */
+ if (!cmd_data->output_name) {
+ rv = run_command(cmd_data, cmd_data->arglist);
+ if (rv) {
+ return rv;
+ }
+ }
+ if (cmd_data->output_name) {
+ append_count_chars(cctemp, cmd_data->arglist);
+ insert_count_chars(cctemp,
+ cmd_data->output_name,
+ cctemp->num - 1);
+ rv = run_command(cmd_data, cctemp);
+ if (rv) {
+ return rv;
+ }
+ clear_count_chars(cctemp);
+ }
+ if (cmd_data->static_name.install) {
+ append_count_chars(cctemp, cmd_data->arglist);
+ insert_count_chars(cctemp,
+ cmd_data->static_name.install,
+ cctemp->num - 1);
+ rv = run_command(cmd_data, cctemp);
+ if (rv) {
+ return rv;
+ }
+#if defined(__APPLE__) && defined(RANLIB)
+ /* From the Apple libtool(1) manpage on Tiger/10.4:
+ * ----
+ * With the way libraries used to be created, errors were possible
+ * if the library was modified with ar(1) and the table of
+ * contents was not updated by rerunning ranlib(1). Thus the
+ * link editor, ld, warns when the modification date of a library
+ * is more recent than the creation date of its table of
+ * contents. Unfortunately, this means that you get the warning
+ * even if you only copy the library.
+ * ----
+ *
+ * This means that when we install the static archive, we need to
+ * rerun ranlib afterwards.
+ */
+ const char *lib_args[3], *static_lib_name;
+ char *tmp;
+ size_t len1, len2;
+ len1 = strlen(cmd_data->arglist->vals[cmd_data->arglist->num - 1]);
+
+ static_lib_name = jlibtool_basename(cmd_data->static_name.install);
+ len2 = strlen(static_lib_name);
+
+ tmp = malloc(len1 + len2 + 2);
+
+ snprintf(tmp, len1 + len2 + 2, "%s/%s",
+ cmd_data->arglist->vals[cmd_data->arglist->num - 1],
+ static_lib_name);
+
+ lib_args[0] = RANLIB;
+ lib_args[1] = tmp;
+ lib_args[2] = NULL;
+ external_spawn(cmd_data, RANLIB, lib_args);
+ free(tmp);
+#endif
+ clear_count_chars(cctemp);
+ }
+ if (cmd_data->shared_name.install) {
+ append_count_chars(cctemp, cmd_data->arglist);
+ insert_count_chars(cctemp,
+ cmd_data->shared_name.install,
+ cctemp->num - 1);
+ rv = run_command(cmd_data, cctemp);
+ if (rv) {
+ return rv;
+ }
+ clear_count_chars(cctemp);
+ }
+ if (cmd_data->module_name.install) {
+ append_count_chars(cctemp, cmd_data->arglist);
+ insert_count_chars(cctemp,
+ cmd_data->module_name.install,
+ cctemp->num - 1);
+ rv = run_command(cmd_data, cctemp);
+ if (rv) {
+ return rv;
+ }
+ clear_count_chars(cctemp);
+ }
+ break;
+ case mLink:
+ if (cmd_data->output == otStaticLibraryOnly ||
+ cmd_data->output == otLibrary) {
+#ifdef RANLIB
+ const char *lib_args[3];
+#endif
+ /* Removes compiler! */
+ cmd_data->program = LIBRARIAN;
+ push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
+ push_count_chars(cmd_data->program_opts,
+ cmd_data->static_name.normal);
+
+ rv = run_command(cmd_data, cmd_data->obj_files);
+ if (rv) {
+ return rv;
+ }
+
+#ifdef RANLIB
+ lib_args[0] = RANLIB;
+ lib_args[1] = cmd_data->static_name.normal;
+ lib_args[2] = NULL;
+ external_spawn(cmd_data, RANLIB, lib_args);
+#endif
+ }
+
+ if (cmd_data->output == otDynamicLibraryOnly ||
+ cmd_data->output == otModule ||
+ cmd_data->output == otLibrary) {
+ cmd_data->program = NULL;
+ clear_count_chars(cmd_data->program_opts);
+
+ append_count_chars(cmd_data->program_opts, cmd_data->arglist);
+ if (cmd_data->output == otModule) {
+#ifdef MODULE_OPTS
+ push_count_chars(cmd_data->program_opts, MODULE_OPTS);
+#endif
+ } else {
+#ifdef SHARED_OPTS
+ push_count_chars(cmd_data->program_opts, SHARED_OPTS);
+#endif
+#ifdef dynamic_link_version_func
+ push_count_chars(cmd_data->program_opts,
+ dynamic_link_version_func(cmd_data->version_info));
+#endif
+ }
+ add_dynamic_link_opts(cmd_data, cmd_data->program_opts);
+
+ rv = run_command(cmd_data, cmd_data->shared_opts.normal);
+ if (rv) {
+ return rv;
+ }
+ }
+ if (cmd_data->output == otProgram) {
+ rv = run_command(cmd_data, cmd_data->arglist);
+ if (rv) {
+ return rv;
+ }
+ }
+ break;
+ case mExecute:
+ {
+ char *l, libpath[PATH_MAX];
+
+ strcpy(libpath, cmd_data->arglist->vals[0]);
+ add_dotlibs(libpath);
+ l = strrchr(libpath, '/');
+ if (!l) l = strrchr(libpath, '\\');
+ if (l) {
+ *l = '\0';
+ l = libpath;
+ } else {
+ l = ".libs/";
+ }
+
+ setenv(LD_LIBRARY_PATH_LOCAL, "./build/lib/.libs/", 1);
+ rv = run_command(cmd_data, cmd_data->arglist);
+ if (rv) {
+ return rv;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void cleanup_tmp_dir(const char *dirname)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char fullname[1024];
+
+ dir = opendir(dirname);
+
+ if (dir == NULL)
+ return;
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_name[0] != '.') {
+ strcpy(fullname, dirname);
+ strcat(fullname, "/");
+ strcat(fullname, entry->d_name);
+ remove(fullname);
+ }
+ }
+
+ rmdir(dirname);
+}
+
+static void cleanup_tmp_dirs(command_t *cmd_data)
+{
+ int d;
+
+ for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
+ cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
+ }
+}
+
+static int ensure_fake_uptodate(command_t *cmd_data)
+{
+ /* FIXME: could do the stat/touch here, but nah... */
+ const char *touch_args[3];
+
+ if (cmd_data->mode == mInstall) {
+ return 0;
+ }
+ if (!cmd_data->fake_output_name) {
+ return 0;
+ }
+
+ touch_args[0] = "touch";
+ touch_args[1] = cmd_data->fake_output_name;
+ touch_args[2] = NULL;
+ return external_spawn(cmd_data, "touch", touch_args);
+}
+
+/* Store the install path in the *.la file */
+static int add_for_runtime(command_t *cmd_data)
+{
+ if (cmd_data->mode == mInstall) {
+ return 0;
+ }
+ if (cmd_data->output == otDynamicLibraryOnly ||
+ cmd_data->output == otLibrary) {
+ FILE *f=fopen(cmd_data->fake_output_name,"w");
+ if (f == NULL) {
+ return -1;
+ }
+ fprintf(f,"%s\n", cmd_data->install_path);
+ fclose(f);
+ return(0);
+ } else {
+ return(ensure_fake_uptodate(cmd_data));
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ command_t cmd_data;
+
+ memset(&cmd_data, 0, sizeof(cmd_data));
+
+ cmd_data.options.pic_mode = pic_UNKNOWN;
+
+ cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.program_opts);
+ cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.arglist);
+ cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.tmp_dirs);
+ cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.obj_files);
+ cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.dep_rpaths);
+ cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.rpaths);
+ cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.static_opts.normal);
+ cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.shared_opts.normal);
+ cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
+ init_count_chars(cmd_data.shared_opts.dependencies);
+
+ cmd_data.mode = mUnknown;
+ cmd_data.output = otGeneral;
+
+ parse_args(argc, argv, &cmd_data);
+ post_parse_fixup(&cmd_data);
+
+ if (cmd_data.mode == mUnknown) {
+ usage(1);
+ }
+
+ rc = run_mode(&cmd_data);
+
+ if (!rc) {
+ add_for_runtime(&cmd_data);
+ }
+
+ cleanup_tmp_dirs(&cmd_data);
+ return rc;
+}
--- /dev/null
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Add these rules only when LIBTOOL is being used.
+ifneq "${LIBTOOL}" ""
+
+# JLIBTOOL - check if we're using the local (fast) jlibtool, rather
+# than the GNU (slow) libtool shell script. If so, add rules
+# to build it.
+
+ifeq "${LIBTOOL}" "JLIBTOOL"
+ JLIBTOOL := ${BUILD_DIR}/make/jlibtool
+
+ # Add a rule to build jlibtool BEFORE any other targets. This
+ # means that we can use it to build the later targets.
+ all install: ${JLIBTOOL}
+
+ # Note that we need to use a compilation rule that does NOT
+ # include referencing ${LIBTOOL}, as we don't have a jlibtool
+ # binary!
+ jlibtool ${JLIBTOOL}: ${top_makedir}/jlibtool.c
+ @mkdir -p $(dir ${JLIBTOOL})
+ ${CC} $< -o ${JLIBTOOL}
+
+ clean: jlibtool_clean
+
+ .PHONY: jlibtool_clean
+ jlibtool_clean:
+ @rm -f ${JLIBTOOL}
+
+ # Tell GNU Make to use this value, rather than anything specified
+ # on the command line.
+ override LIBTOOL := ${JLIBTOOL}
+endif # else we're not using jlibtool
+
+# When using libtool, it produces a '.libs' directory. Ensure that it
+# is removed on "make clean", too.
+#
+clean: .libs_clean
+
+.PHONY: .libs_clean
+.libs_clean:
+ @rm -rf ${BUILD_DIR}/.libs/
+
+# Re-define compilers and linkers
+#
+OBJ_EXT = lo
+COMPILE.c = ${LIBTOOL} --silent --mode=compile ${CC}
+COMPILE.cxx = ${LIBTOOL} --mode=compile ${CXX}
+LINK.c = ${LIBTOOL} --silent --mode=link ${CC}
+LINK.cxx = ${LIBTOOL} --mode=link ${CXX}
+PROGRAM_INSTALL = ${LIBTOOL} --silent --mode=install ${INSTALL}
+
+
+# LIBTOOL_ENDINGS - Given a library ending in ".a" or ".so", replace that
+# extension with ".la".
+#
+define LIBTOOL_ENDINGS
+$(patsubst %.a,%.la,$(patsubst %.so,%.la,${1}))
+endef
+
+# ADD_TARGET_RULE.la - Build a ".la" target.
+#
+# USE WITH EVAL
+#
+define ADD_TARGET_RULE.la
+ # So "make ${1}" works
+ .PHONY: ${1}
+ ${1}: $${${1}_BUILD}/${1}
+
+ # Create libtool library ${1}
+ $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PREREQS}
+ @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+ @$(ECHO) LINK $${${1}_BUILD}/${1}
+ @$${${1}_LINKER} -o $${${1}_BUILD}/${1} $${RPATH_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS}
+ @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_RELINK_RULE.exe - Parametric "function" that adds a rule to relink
+# the target before installation, so that the paths are correct.
+#
+# USE WITH EVAL
+#
+define ADD_RELINK_RULE.exe
+ ${1}: $${${1}_BUILD}/$${${1}_RELINK}
+
+ # used to fix up RPATH for ${1} on install.
+ $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_R_PRLIBS}
+ @$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
+ @$${${1}_LINKER} -o $${${1}_BUILD}/$${${1}_RELINK} $${RELINK_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_R_PRLIBS} \
+ $${LDLIBS} $${${1}_LDLIBS}
+ @$${${1}_POSTMAKE}
+endef
+
+# ADD_RELINK_RULE.la - Parametric "function" that adds a rule to relink
+# the target before installation, so that the paths are correct.
+#
+# USE WITH EVAL
+#
+define ADD_RELINK_RULE.la
+ ${1}: $${${1}_BUILD}/$${${1}_RELINK}
+
+ # used to fix up RPATH for ${1} on install.
+ $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PREREQS}
+ @$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
+ @$${${1}_LINKER} -o $${${1}_BUILD}/$${${1}_RELINK} $${RELINK_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS}
+ @$${${1}_POSTMAKE}
+
+endef
+
+# By default, if libdir is defined, we build shared libraries.
+# However, we can disable shared libraries if explicitly told to.
+ifneq "${libdir}" ""
+ ifneq "bm_shared_libs" "no"
+ bm_shared_libs := yes
+ endif
+endif
+
+# Default to building static libraries, too.
+ifneq "${bm_static_libs}" "no"
+ bm_static_libs := yes
+endif
+
+# Check if we build shared libraries.
+ifeq "${bm_shared_libs}" "yes"
+ # RPATH : flags use to build executables that can be run
+ # from the build directory / source tree.
+ # RELINK : flags use to build executables that are installed,
+ # with no dependency on the source.
+ RPATH_FLAGS := -rpath $(abspath ${BUILD_DIR})/lib/.libs -rdynamic
+ RELINK_FLAGS := -rpath ${libdir} -rdynamic
+ RELINK := relink/
+
+ ifneq "${bm_static_libs}" "yes"
+ RPATH_FLAGS += --shared
+ RELINK_FLAGS += --shared
+ endif
+else
+ ifneq "${bm_static_libs}" "yes"
+ $(error Building without static libraries requires you to set 'INSTALL' or 'libdir')
+ endif
+
+ RPATH_FLAGS := -static
+endif
+
+# UPDATE_TARGET_ENDINGS - Function to turn target into a libtool target
+# e.g. "libfoo.a" -> libfoo.la"
+#
+# If the target is an executable, then its extension doesn't change
+# when we use libtool, and we don't do any re-writing.
+#
+# USE WITH EVAL
+#
+define ADD_LIBTOOL_SUFFIX
+ ifneq "$$(call LIBTOOL_ENDINGS,$${TGT})" "$${TGT}"
+ TGT_NOLIBTOOL := $${TGT}
+ TGT := $$(call LIBTOOL_ENDINGS,$${TGT})
+ $${TGT}_NOLIBTOOL := $${TGT_NOLIBTOOL}
+ endif
+
+ ifneq "$${RELINK_FLAGS}" ""
+ $${TGT}_RELINK := ${RELINK}$${TGT}
+ endif
+
+ # re-write all of the dependencies to have the libtool endings.
+ TGT_PREREQS := $$(call LIBTOOL_ENDINGS,$${TGT_PREREQS})
+endef
+
+# ADD_LIBTOOL_TARGET - Function to ensure that the object files depend
+# on our jlibtool target. This ensures that jlibtool is built before
+# it's used to build the object files.
+#
+# USE WITH EVAL
+#
+define ADD_LIBTOOL_TARGET
+ ifneq "${JLIBTOOL}" ""
+ $${$${TGT}_OBJS}: $${JLIBTOOL}
+ endif
+
+ ifneq "$${$${TGT}_NOLIBTOOL}" ""
+ $$(notdir $${$${TGT}_NOLIBTOOL}): $${TGT}
+ endif
+
+ # If we need to relink, add the relink targets now.
+ ifneq "$${$${TGT}_RELINK}" ""
+ # add rules to relink the target
+
+ $${TGT}_R_PRLIBS := $$(subst /lib/,/lib/relink/,$${$${TGT}_PRLIBS})
+
+ $$(eval $$(call ADD_RELINK_RULE$${$${TGT}_SUFFIX},$${TGT}))
+ endif
+
+endef
+
+
+endif
--- /dev/null
+# We don't use boilermake here because we want to run the test-app
+# as a self-contained system that runs boilermake.
+#
+
+all: run-tests
+
+APP := ./test-app/build/bin/talk
+
+.PHONY: run-tests
+run-tests:
+ ${MAKE} clean
+ ${MAKE} -C test-app/
+ ${APP} > found.txt
+ diff expected.txt found.txt
+ ${MAKE} -C test-app/ DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh install
+ find R/* -print > found-install.txt
+ diff expected-install.txt found-install.txt
+ ${APP} > found.txt
+ diff expected.txt found.txt
+ ${MAKE} -C test-app/ DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh uninstall
+ find R/* -print > found-install.txt
+ diff empty-install.txt found-install.txt
+ ${MAKE} clean
+ ${MAKE} -C test-app/ LIBTOOL=JLIBTOOL DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh all
+ ${APP} > found.txt
+ diff expected.txt found.txt
+ ${MAKE} -C test-app/ LIBTOOL=JLIBTOOL DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh install
+# don't do "find", as we have *.la files installed, rather than *.a
+ ${APP} > found.txt
+ diff expected.txt found.txt
+ ${MAKE} clean
+ rm -rf R found found-install.txt
+
+clean: clean.local
+
+clean.local:
+ ${MAKE} -C test-app/ clean
+ ${MAKE} -C test-app/ LIBTOOL=x clean
+ rm -rf ./R *~ found.txt found-install.txt
+
+check-legacy:
+ @grep '$$(' `find test-app/build/make -type f -name "*\.mk" -print` || true
+ @grep ' /' `find test-app/build/make -type f -name "*\.mk" -print` || true
+ @grep ' build' `find test-app/build/make -type f -name "*\.mk" -print` || true
$INCLUDE dictionary.rfc4818
$INCLUDE dictionary.rfc4849
$INCLUDE dictionary.rfc5176
+$INCLUDE dictionary.rfc5447
$INCLUDE dictionary.rfc5580
$INCLUDE dictionary.rfc5607
$INCLUDE dictionary.rfc5904
ATTRIBUTE Manzara-Tariff-Units 7 integer
ATTRIBUTE Manzara-Tariff-Type 8 integer
ATTRIBUTE Manzara-ECP-Session-Key 9 octets
+ATTRIBUTE Manzara-Map-Name 10 string
+ATTRIBUTE Manzara-Map-Key 11 string
+ATTRIBUTE Manzara-Map-Value 12 string
+ATTRIBUTE Manzara-Map-Error 13 string
+ATTRIBUTE Manzara-Service-Type 14 string
VALUE Manzara-Tariff-Type MMS-Picture 1
VALUE Manzara-Tariff-Type Unused 2
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2012 The FreeRADIUS Server project and contributors
+#
+# Attributes and values defined in RFC 5447.
+# http://www.ietf.org/rfc/rfc5447.txt
+#
+# $Id$
+#
+
+# 64-bit bit field
+ATTRIBUTE MIP6-Feature-Vector 124 octets
+ATTRIBUTE MIP6-Home-Link-Prefix 125 ipv6prefix
@$(MAKE) $(MFLAGS) X=$(X)src/ -C $@ $(WHAT_TO_MAKE)
freeradius-devel:
- ln -s include freeradius-devel
+ ln -sf include freeradius-devel
--- /dev/null
+# add this dependency BEFORE including the other submakefiles.
+all: ${BUILD_DIR}/make/include/freeradius-devel src/freeradius-devel
+
+#TARGET := src/freeradius-devel
+
+# Ensure that the devel files have access to radpaths.h
+${BUILD_DIR}/make/include/freeradius-devel: src/include/radpaths.h
+ @[ -e $@ ] || (mkdir -p $(dir $@) && ln -s ${top_builddir}/src/include $@)
+
+src/freeradius-devel: src/include/radpaths.h
+ @[ -e $@ ] || ln -s include $@
+
+SUBMAKEFILES := include/all.mk lib/all.mk modules/all.mk main/all.mk
+
--- /dev/null
+#
+# Makefile
+#
+# Version: $Id$
+#
+
+HEADERS = autoconf.h conf.h conffile.h detail.h dhcp.h event.h hash.h heap.h \
+ ident.h libradius.h md4.h md5.h missing.h modcall.h modules.h \
+ packet.h rad_assert.h radius.h radiusd.h radpaths.h \
+ radutmp.h realms.h sha1.h stats.h sysutmp.h token.h \
+ udpfromto.h vmps.h vqp.h
+
+# Our target
+TARGET := src/include/radpaths.h
+
+src/include/radpaths.h: src/include/build-radpaths-h
+ cd src/include && /bin/sh build-radpaths-h
+
+# global install depends on the local rule
+install: install.src.include
+
+# define the installation directory
+SRC_INCLUDE_DIR := ${R}${includedir}/freeradius
+
+# the local rule depends on the installed headers
+install.src.include: $(addprefix ${SRC_INCLUDE_DIR}/,${HEADERS})
+
+# the installed headers require a directory
+$(addprefix ${SRC_INCLUDE_DIR}/,${HEADERS}): ${SRC_INCLUDE_DIR}/
+
+# make the directory
+.PHONY:
+${SRC_INCLUDE_DIR}/:
+ $(INSTALL) -d -m 755 $@
+
+# install the headers by re-writing the local files
+${SRC_INCLUDE_DIR}/%.h: ${top_srcdir}/src/include/%.h
+ @echo INSTALL $(notdir $<)
+ @sed 's/^#include <freeradius-devel/#include <freeradius/' < $< > $@
+ @chmod 644 $@
uint16_t dst_port;
int id;
unsigned int code;
- uint32_t hash;
uint8_t vector[AUTH_VECTOR_LEN];
struct timeval timestamp;
uint8_t *data;
DICT_ATTR *dict_attrbyname(const char *attr);
DICT_VALUE *dict_valbyattr(unsigned int attr, unsigned int vendor, int val);
DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, const char *val);
+const char *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value);
int dict_vendorbyname(const char *name);
DICT_VENDOR *dict_vendorbyvalue(int vendor);
#ifndef WITHOUT_LIBLTDL
#ifdef WITH_SYSTEM_LTDL
-#include "ltdl.h"
+#include <ltdl.h>
#else
#include "libltdl/ltdl.h"
#endif
extern "C" {
#endif
-uint32_t fr_request_packet_hash(const RADIUS_PACKET *packet);
-uint32_t fr_reply_packet_hash(const RADIUS_PACKET *packet);
int fr_packet_cmp(const RADIUS_PACKET *a, const RADIUS_PACKET *b);
int fr_inaddr_any(fr_ipaddr_t *ipaddr);
void fr_request_from_reply(RADIUS_PACKET *request,
#define VENDORPEC_FREERADIUS 11344
#define VENDORPEC_WIMAX 24757
#define VENDORPEC_EXTENDED (1 << 25)
+#define VENDORPEC_UKERNA 25622
/*
* Vendor specific attributes
#define PW_VQP_MAC 0x2c06
#define PW_VQP_UNKNOWN 0x2c07
#define PW_VQP_COOKIE 0x2c08
+
+/*
+ * JANET's code for transporting eap channel binding data over ttls
+ */
+
+#define PW_UKERNA_CHBIND 134
int ocsp_enable;
int ocsp_override_url;
char *ocsp_url;
+ int ocsp_use_nonce;
X509_STORE *ocsp_store;
+ int ocsp_timeout;
+ int ocsp_softfail;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
char *ecdh_curve;
#endif
#endif
+
+#ifdef PSK_MAX_IDENTITY_LEN
+ char *psk_identity;
+ char *psk_password;
+#endif
+
};
#ifdef __cplusplus
--- /dev/null
+#
+# Makefile
+#
+# Version: $Id$
+#
+
+SOURCES := dict.c filters.c hash.c hmac.c hmacsha1.c isaac.c log.c \
+ misc.c missing.c md4.c md5.c print.c radius.c rbtree.c \
+ sha1.c snprintf.c strlcat.c strlcpy.c token.c udpfromto.c \
+ valuepair.c fifo.c packet.c event.c getaddrinfo.c vqp.c \
+ heap.c dhcp.c tcp.c
+
+INCLUDES = ../include/radius.h ../include/libradius.h \
+ ../include/missing.h ../include/autoconf.h \
+ ../include/ident.h
+
+SRC_CFLAGS := -D_LIBRADIUS -I$(top_builddir)/src
+
+TARGET := libfreeradius-radius.a
if (packet->data_len < MIN_PACKET_SIZE) {
fr_strerror_printf("DHCP packet is too small (%d < %d)",
- packet->data_len, MIN_PACKET_SIZE);
+ (int) packet->data_len, MIN_PACKET_SIZE);
rad_free(&packet);
return NULL;
}
return 0;
#else
+ fd = fd; /* -Wunused */
+ interface = interface; /* -Wunused */
+ macaddr = macaddr; /* -Wunused */
+ ip = ip; /* -Wunused */
+
fr_strerror_printf("Adding ARP entry is unsupported on this system");
return -1;
#endif
/*
* TLV's can be only one octet.
*/
- if ((value <= 0) || ((value & ~fr_attr_mask[tlv_depth]) != 0)) {
+ if ((value == 0) || ((value & ~fr_attr_mask[tlv_depth]) != 0)) {
fr_strerror_printf( "dict_init: %s[%d]: sub-tlv has invalid attribute number",
fn, line);
return -1;
}
/*
+ * Associate a value with an attribute and return it.
+ */
+const char *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value)
+{
+ DICT_VALUE *dv;
+
+ dv = dict_valbyattr(attr, vendor, value);
+ if (!dv) return "";
+
+ return dv->name;
+}
+
+/*
* Get a value by its name, keyed off of an attribute.
*/
DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, const char *name)
#include <fcntl.h>
/*
- * Take the key fields of a request packet, and convert it to a
- * hash.
- */
-uint32_t fr_request_packet_hash(const RADIUS_PACKET *packet)
-{
- uint32_t hash;
-
- if (packet->hash) return packet->hash;
-
- hash = fr_hash(&packet->sockfd, sizeof(packet->sockfd));
- hash = fr_hash_update(&packet->src_port, sizeof(packet->src_port),
- hash);
- hash = fr_hash_update(&packet->dst_port,
- sizeof(packet->dst_port), hash);
- hash = fr_hash_update(&packet->src_ipaddr.af,
- sizeof(packet->src_ipaddr.af), hash);
-
- /*
- * The caller ensures that src & dst AF are the same.
- */
- switch (packet->src_ipaddr.af) {
- case AF_INET:
- hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
- sizeof(packet->src_ipaddr.ipaddr.ip4addr),
- hash);
- hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
- sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
- hash);
- break;
- case AF_INET6:
- hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
- sizeof(packet->src_ipaddr.ipaddr.ip6addr),
- hash);
- hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
- sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
- hash);
- break;
- default:
- break;
- }
-
- return fr_hash_update(&packet->id, sizeof(packet->id), hash);
-}
-
-
-/*
- * Take the key fields of a reply packet, and convert it to a
- * hash.
- *
- * i.e. take a reply packet, and find the hash of the request packet
- * that asked for the reply. To do this, we hash the reverse fields
- * of the request. e.g. where the request does (src, dst), we do
- * (dst, src)
- */
-uint32_t fr_reply_packet_hash(const RADIUS_PACKET *packet)
-{
- uint32_t hash;
-
- hash = fr_hash(&packet->sockfd, sizeof(packet->sockfd));
- hash = fr_hash_update(&packet->id, sizeof(packet->id), hash);
- hash = fr_hash_update(&packet->src_port, sizeof(packet->src_port),
- hash);
- hash = fr_hash_update(&packet->dst_port,
- sizeof(packet->dst_port), hash);
- hash = fr_hash_update(&packet->src_ipaddr.af,
- sizeof(packet->src_ipaddr.af), hash);
-
- /*
- * The caller ensures that src & dst AF are the same.
- */
- switch (packet->src_ipaddr.af) {
- case AF_INET:
- hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
- sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
- hash);
- hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
- sizeof(packet->src_ipaddr.ipaddr.ip4addr),
- hash);
- break;
- case AF_INET6:
- hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
- sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
- hash);
- hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
- sizeof(packet->src_ipaddr.ipaddr.ip6addr),
- hash);
- break;
- default:
- break;
- }
-
- return fr_hash_update(&packet->id, sizeof(packet->id), hash);
-}
-
-
-/*
* See if two packets are identical.
*
* Note that we do NOT compare the authentication vectors.
*/
case FLAG_ENCRYPT_USER_PASSWORD:
if (original) {
- rad_pwdecode(buffer,
+ rad_pwdecode((char *) buffer,
vp->length, secret,
original->vector);
} else {
- rad_pwdecode(buffer,
+ rad_pwdecode((char *) buffer,
vp->length, secret,
packet->vector);
}
buffer[253] = '\0';
if (vp->attribute == PW_USER_PASSWORD) {
- vp->length = strlen(buffer);
+ vp->length = strlen((char *) buffer);
}
break;
memcpy(buffer, my_digest,
AUTH_VECTOR_LEN );
buffer[AUTH_VECTOR_LEN] = '\0';
- vp->length = strlen(buffer);
+ vp->length = strlen((char *) buffer);
}
break;
session.c threads.c util.c valuepair.c version.c \
xlat.c process.c realms.c evaluate.c vmps.c detail.c
ifneq ($(OPENSSL_LIBS),)
-SERVER_SRCS += cb.c tls.c
+SERVER_SRCS += cb.c tls.c tls_listen.c
endif
SERVER_OBJS += $(SERVER_SRCS:.c=.lo)
VFLAGS = -DRADIUSD_MAJOR_VERSION=$(RADIUSD_MAJOR_VERSION)
VFLAGS += -DRADIUSD_MINOR_VERSION=$(RADIUSD_MINOR_VERSION)
MODULE_LIBS = $(STATIC_MODULES)
-BINARIES = radiusd radwho radclient radmin radconf2xml radattr
+BINARIES = radiusd$(EXEEXT) radwho$(EXEEXT) radclient$(EXEEXT) radmin$(EXEEXT) radconf2xml$(EXEEXT) radattr$(EXEEXT)
#
# The RADIUS sniffer
#
PCAP_LIBS = @PCAP_LIBS@
ifneq ($(PCAP_LIBS),)
-BINARIES += radsniff
+BINARIES += radsniff$(EXEEXT)
endif
#
$(SERVER_OBJS): $(INCLUDES)
-radiusd: $(SERVER_OBJS) $(MODULE_OBJS) $(LIBRADIUS)
+radiusd$(EXEEXT): $(SERVER_OBJS) $(MODULE_OBJS) $(LIBRADIUS)
$(LIBTOOL) --quiet --mode=link $(CC) -export-dynamic -dlopen self \
$(LDFLAGS) $(LINK_MODE) -o $@ $(SERVER_OBJS) \
$(MODULE_LIBS) $(LIBRADIUS) $(LIBS) $(SNMP_LIBS) \
# It's #include'd for simplicity. This should be fixed...
listen.lo: listen.c dhcpd.c command.c
- @echo CC $<
- @$(LIBTOOL) --quiet --mode=compile $(CC) $(CFLAGS) $(INCLTDL) -c listen.c
#
# Helper programs
MSCHAP_OBJS := ../modules/rlm_mschap/smbdes.lo ../modules/rlm_mschap/mschap.lo
-radclient: radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS)
+radclient$(EXEEXT): radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS)
@echo LINK $< ...
@$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radclient radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS) $(LIBS)
radsniff.lo: radsniff.c $(INCLUDES) ../include/radsniff.h
-radsniff: radsniff.lo $(LIBRADIUS)
+radsniff$(EXEEXT): radsniff.lo $(LIBRADIUS)
@echo LINK $@ $<
@$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radsniff radsniff.lo $(LIBRADIUS) $(LIBS) $(PCAP_LIBS)
radwho.lo: radwho.c $(INCLUDES)
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radwho.c
-radwho: radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS)
+radwho$(EXEEXT): radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radwho radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS) $(LIBS)
-radmin: radmin.lo $(LIBRADIUS) util.lo log.lo conffile.lo
+radmin$(EXEEXT): radmin.lo $(LIBRADIUS) util.lo log.lo conffile.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ $(LIBREADLINE) $(LIBS)
-radconf2xml: radconf2xml.lo $(LIBRADIUS) util.lo log.lo conffile.lo
+radconf2xml$(EXEEXT): radconf2xml.lo $(LIBRADIUS) util.lo log.lo conffile.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ $(LIBS)
-radattr: radattr.lo $(LIBRADIUS)
+radattr$(EXEEXT): radattr.lo $(LIBRADIUS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radattr radattr.lo $(LIBRADIUS) $(LIBS)
dhclient.lo: dhclient.c $(INCLUDES)
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c dhclient.c
# Don't install this for now.
-dhclient: dhclient.lo $(LIBRADIUS)
+dhclient$(EXEEXT): dhclient.lo $(LIBRADIUS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o dhclient dhclient.lo $(LIBRADIUS) $(LIBS)
clean:
*/
vp = pairfind(request->config_items, PW_ACCT_TYPE, 0);
if (vp) {
- DEBUG2(" Found Acct-Type %s", vp->vp_strvalue);
acct_type = vp->vp_integer;
+ DEBUG2(" Found Acct-Type %s",
+ dict_valnamebyattr(PW_ACCT_TYPE, 0, acct_type));
}
result = module_accounting(acct_type, request);
switch (result) {
--- /dev/null
+SUBMAKEFILES := radclient.mk radiusd.mk radsniff.mk
auth_type = pairfind(request->config_items,
PW_AUTH_TYPE, 0);
- if (auth_type && (auth_type->vp_strvalue[0] != '\0')) {
+ if (auth_type) {
snprintf(clean_password, sizeof(clean_password),
"<via Auth-Type = %s>",
- auth_type->vp_strvalue);
+ dict_valnamebyattr(PW_AUTH_TYPE, 0,
+ auth_type->vp_integer));
} else {
strcpy(clean_password, "<no User-Password attribute>");
}
*/
cur_config_item = request->config_items;
while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE, 0))) != NULL) {
- DICT_VALUE *dv;
auth_type = auth_type_pair->vp_integer;
auth_type_count++;
- dv = dict_valbyattr(PW_AUTH_TYPE,
- auth_type_pair->vp_integer, 0);
RDEBUG2("Found Auth-Type = %s",
- (dv != NULL) ? dv->name : "?");
+ dict_valnamebyattr(PW_AUTH_TYPE, 0, auth_type));
cur_config_item = auth_type_pair->next;
if (auth_type == PW_AUTHTYPE_REJECT) {
*/
vp = pairfind(request->config_items, PW_POST_AUTH_TYPE, 0);
if (vp) {
- RDEBUG2("Using Post-Auth-Type %s", vp->vp_strvalue);
postauth_type = vp->vp_integer;
+ RDEBUG2("Using Post-Auth-Type %s",
+ dict_valnamebyattr(PW_POST_AUTH_TYPE, 0, postauth_type));
}
result = module_post_auth(postauth_type, request);
switch (result) {
if (!autz_retry) {
tmp = pairfind(request->config_items, PW_AUTZ_TYPE, 0);
if (tmp) {
- RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
autz_type = tmp->vp_integer;
+ RDEBUG2("Using Autz-Type %s",
+ dict_valnamebyattr(PW_AUTZ_TYPE, 0, autz_type));
autz_retry = 1;
goto autz_redo;
}
tmp = pairfind(request->config_items, PW_SESSION_TYPE, 0);
if (tmp) {
- RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
session_type = tmp->vp_integer;
+ RDEBUG2("Using Session-Type %s",
+ dict_valnamebyattr(PW_SESSION_TYPE, 0, session_type));
}
/*
VALUE_PAIR *input_pairs,
int shell_escape)
{
- VALUE_PAIR *vp;
- char mycmd[1024];
const char *from;
- char *p, *to;
+ char *to;
+#ifndef __MINGW32__
+ char *p;
+ VALUE_PAIR *vp;
+ int n;
int to_child[2] = {-1, -1};
int from_child[2] = {-1, -1};
pid_t pid;
+#endif
int argc = -1;
int i;
- int n, left;
+ int left;
char *argv[MAX_ARGV];
char argv_buf[4096];
#define MAX_ENVP 1024
char *envp[MAX_ENVP];
+ char mycmd[1024];
if (strlen(cmd) > (sizeof(mycmd) - 1)) {
radlog(L_ERR|L_CONS, "Command line is too long");
}
return pid;
+#else
+ if (exec_wait) {
+ radlog(L_ERR, "Exec-Program-Wait is not supported");
+ return -1;
+ }
+
+ {
+ /*
+ * The _spawn and _exec families of functions are
+ * found in Windows compiler libraries for
+ * portability from UNIX. There is a variety of
+ * functions, including the ability to pass
+ * either a list or array of parameters, to
+ * search in the PATH or otherwise, and whether
+ * or not to pass an environment (a set of
+ * environment variables). Using _spawn, you can
+ * also specify whether you want the new process
+ * to close your program (_P_OVERLAY), to wait
+ * until the new process is finished (_P_WAIT) or
+ * for the two to run concurrently (_P_NOWAIT).
+
+ * _spawn and _exec are useful for instances in
+ * which you have simple requirements for running
+ * the program, don't want the overhead of the
+ * Windows header file, or are interested
+ * primarily in portability.
+ */
+
+ /*
+ * FIXME: check return code... what is it?
+ */
+ _spawnve(_P_NOWAIT, argv[0], argv, envp);
+ }
+
+ return 0;
+#endif
}
/** Read from the child process.
* @param left length of buffer.
* @return -1 on error, or length of output.
*/
-int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer, int left) {
-
- int done;
+int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer,
+ int left)
+{
+ int done = 0;
+#ifndef __MINGW32__
int status;
struct timeval start;
#ifdef O_NONBLOCK
* Read from the pipe until we doesn't get any more or
* until the message is full.
*/
- done = 0;
gettimeofday(&start, NULL);
while (1) {
int rcode;
left -= status;
if (left <= 0) break;
}
-
+#endif /* __MINGW32__ */
return done;
}
VALUE_PAIR **output_pairs,
int shell_escape)
{
+ pid_t pid;
+ int from_child;
+#ifndef __MINGW32__
VALUE_PAIR *vp;
char *p;
- int from_child;
- pid_t pid, child_pid;
+ pid_t child_pid;
int comma = 0;
int status;
int n, done;
char answer[4096];
+#endif
pid = radius_start_program(cmd, request, exec_wait, NULL, &from_child, input_pairs, shell_escape);
if (pid < 0) {
if (!exec_wait)
return 0;
+#ifndef __MINGW32__
done = radius_readfrom_program(from_child, pid, 10, answer, sizeof(answer));
if (done < 0) {
/*
radlog(L_ERR|L_CONS, "Exec-Program: Abnormal child exit: %s",
strerror(errno));
- return 1;
-#else
- msg_len = msg_len; /* -Wunused */
-
- if (exec_wait) {
- radlog(L_ERR, "Exec-Program-Wait is not supported");
- return -1;
- }
-
- /*
- * We're not waiting, so we don't look for a
- * message, or VP's.
- */
- user_msg = NULL;
- output_pairs = NULL;
+#endif /* __MINGW32__ */
- {
- /*
- * The _spawn and _exec families of functions are
- * found in Windows compiler libraries for
- * portability from UNIX. There is a variety of
- * functions, including the ability to pass
- * either a list or array of parameters, to
- * search in the PATH or otherwise, and whether
- * or not to pass an environment (a set of
- * environment variables). Using _spawn, you can
- * also specify whether you want the new process
- * to close your program (_P_OVERLAY), to wait
- * until the new process is finished (_P_WAIT) or
- * for the two to run concurrently (_P_NOWAIT).
-
- * _spawn and _exec are useful for instances in
- * which you have simple requirements for running
- * the program, don't want the overhead of the
- * Windows header file, or are interested
- * primarily in portability.
- */
-
- /*
- * FIXME: check return code... what is it?
- */
- _spawnve(_P_NOWAIT, argv[0], argv, envp);
- }
-
- return 0;
-#endif
+ return 1;
}
void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name)
/*
* Non-blocking sockets must handle this.
*/
+#ifdef EWOULDBLOCK
if (errno == EWOULDBLOCK) {
return 0;
}
+#endif
DEBUG2(" ... failed to accept connection.");
return -1;
{
rad_listen_t *this;
listen_socket_t *sock;
-#ifndef NDEBUG
char buffer[256];
-#endif
if (!home) return 0;
{ NULL, 0 }
};
+int log_dates_utc = 0;
+
+
/*
* Log the message to the logfile. Include the severity and
* a time stamp.
time_t timeval;
timeval = time(NULL);
- CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
+#ifdef HAVE_GMTIME_R
+ if (log_dates_utc) {
+ struct tm utc;
+ gmtime_r(&timeval, &utc);
+ asctime_r(&utc, buffer + len);
+ } else
+#endif
+ CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
s = strrchr(buffer, '\n');
if (s) {
s[1] = '\0';
}
- s = fr_int2str(levels, (lvl & ~L_CONS), ": ");
-
- strcat(buffer, s);
+ strcat(buffer, fr_int2str(levels, (lvl & ~L_CONS), ": "));
len = strlen(buffer);
}
struct main_config_t mainconfig;
char *request_log_file = NULL;
char *debug_condition = NULL;
+extern int log_dates_utc;
typedef struct cached_config_t {
struct cached_config_t *next;
{ "log", PW_TYPE_SUBSECTION, 0, NULL, (const void *) logdest_config },
{ "log_file", PW_TYPE_STRING_PTR, 0, &mainconfig.log_file, NULL },
{ "log_destination", PW_TYPE_STRING_PTR, 0, &radlog_dest, NULL },
+ { "use_utc", PW_TYPE_BOOLEAN, 0, &log_dates_utc, NULL },
{ NULL, -1, 0, NULL, NULL }
};
{ "msg_badpass", PW_TYPE_STRING_PTR, 0, &mainconfig.auth_badpass_msg, NULL},
{ "msg_goodpass", PW_TYPE_STRING_PTR, 0, &mainconfig.auth_goodpass_msg, NULL},
+ { "use_utc", PW_TYPE_BOOLEAN, 0, &log_dates_utc, NULL },
+
{ NULL, -1, 0, NULL, NULL }
};
int lt_dlinit(void)
{
- char *p, *val;
+ char *p;
+ const char *val;
char buffer[1024];
/*
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
if (!rcode) {
+#ifdef HAVE_PTHREAD_H
if (proxy_no_new_sockets) return 0;
+#endif
/*
* Also locks the proxy mutex, so we have to call
}
+#ifdef HAVE_PTHREAD_H
STATE_MACHINE_DECL(coa_running)
{
TRACE_STATE_MACHINE;
break;
}
}
+#endif /* HAVE_PTHREAD_H */
/*
&sock->other_ipaddr, sock->other_port,
this)) {
+#ifdef HAVE_PTHREAD_H
proxy_no_new_sockets = TRUE;
+#endif
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
/*
if (sock->home) {
sock->home->num_connections++;
+#ifdef HAVE_PTHREAD_H
/*
* If necessary, add it to the list of
* new proxy listeners.
this->next = proxy_listener_list;
proxy_listener_list = this;
}
+#endif
}
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
#ifdef WITH_TCP
#ifdef WITH_PROXY
+#ifdef HAVE_PTHREAD_H
/*
* Add event handlers for idle timeouts && maximum lifetime.
*/
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
}
+#endif /* HAVE_PTHREAD_H */
#endif /* WITH_PROXY */
#endif /* WITH_TCP */
}
--- /dev/null
+TGT_PREREQS := libfreeradius-radius.a
+SRC_CFLAGS := -I${top_srcdir}/src/modules/rlm_mschap
+SRC_CFLAGS += -DRADIUSD_VERSION=\"${RADIUSD_VERSION}\"
+
+TGT_LDLIBS := $(LIBS)
+
+SOURCES := radclient.c ${top_srcdir}/src/modules/rlm_mschap/smbdes.c \
+ ${top_srcdir}/src/modules/rlm_mschap/mschap.c
+
+TARGET := radclient
/*
* For configuration file stuff.
*/
-char *radius_dir = RADDBDIR;
+const char *raddb_dir = RADDBDIR;
const char *progname = "radconf2xml";
/*
fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
exit(1);
}
- radius_dir = optarg;
+ raddb_dir = optarg;
break;
default:
}
}
- snprintf(buffer, sizeof(buffer), "%s/%s.conf", radius_dir, name);
+ snprintf(buffer, sizeof(buffer), "%s/%s.conf", raddb_dir, name);
cs = cf_file_read(buffer);
if (!cs) {
fprintf(stderr, "%s: Errors reading %s\n",
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
- fprintf(stderr, "%s: Unable to initialize socket library.\n");
+ fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
return 1;
}
}
--- /dev/null
+SOURCES := acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
+ listen.c log.c mainconfig.c modules.c modcall.c \
+ radiusd.c stats.c soh.c connection.c dhcpd.c \
+ session.c threads.c util.c valuepair.c version.c \
+ xlat.c process.c realms.c evaluate.c vmps.c detail.c
+ifneq ($(OPENSSL_LIBS),)
+SOURCES += cb.c tls.c tls_listen.c
+endif
+
+SRC_CFLAGS := -DHOSTINFO=\"${HOSTINFO}\"
+SRC_CFLAGS += -DRADIUSD_VERSION=\"${RADIUSD_VERSION}\"
+SRC_CFLAGS += $(OPENSSL_INCLUDE)
+TGT_INSTALLDIR := ${sbindir}
+TGT_LDLIBS := $(OPENSSL_LIBS)
+TGT_LDFLAGS := $(LIBS) $(LCRYPT)
+
+TGT_PREREQS := libfreeradius-radius.a $(filter rlm_%,${ALL_TGTS})
+
+ifneq "${LIBTOOL}" ""
+SRC_FLAGS += -DWITH_DLOPEN
+else
+${DIR}/modules.c: ${BUILD_DIR}/make/include/lt_dlmodules.c
+
+# Find the modules
+ALL_MODULES := $(patsubst %.a,%,$(filter rlm_%,${ALL_TGTS}))
+ALL_MODULES := $(patsubst %.la,%,$(filter rlm_%,${ALL_MODULES}))
+
+# Filter out ones with additional library dependencies.
+# For the future, go through ALL modules and add their library dependencies
+# to the TGT_LDLIBS.
+ALL_MODULES := $(filter-out rlm_perl rlm_ldap rlm_pam rlm_krb5 rlm_python,${ALL_MODULES})
+
+# EAP and SQL require different variable declarations.
+EAP_MODULES := $(filter rlm_eap_%,${ALL_MODULES})
+SQL_MODULES := $(filter rlm_sql_%,${ALL_MODULES})
+
+BASE_MODULES := $(filter-out ${EAP_MODULES} ${SQL_MODULES},${ALL_MODULES})
+
+#
+# Create the intermediate file which links to the modules.
+# And have it depend on this Makefile, which creates it.
+#
+${BUILD_DIR}/make/include/lt_dlmodules.c: $(addprefix ${BUILD_DIR}/lib/,$(filter rlm_%,${ALL_TGTS})) $(lastword ${MAKEFILE_LIST})
+ @rm -f $@
+ @for x in ${BASE_MODULES}; do \
+ echo "extern module_t $$x;" >> $@; \
+ done
+ @for x in ${EAP_MODULES}; do \
+ echo "extern EAP_TYPE $$x;" >> $@; \
+ done
+ @for x in ${SQL_MODULES}; do \
+ echo "extern rlm_sql_module_t $$x;" >> $@; \
+ done
+ @echo "static const lt_dlmodule_t lt_dlmodules[] = {" >> $@
+ @for x in ${ALL_MODULES}; do \
+ echo "{ \"$$x\", &$$x }," >> $@; \
+ done
+ @echo "{ NULL, NULL }" >> $@
+ @echo "};" >> $@
+endif
+
+# Libraries can't depend on libraries (oops), so make the binary
+# depend on the EAP code...
+ifneq "$(filter rlm_eap_%,${ALL_TGTS})" ""
+TGT_PREREQS += libfreeradius-eap.a
+endif
+
+TARGET := radiusd
exit(1);
} else {
- descr = pcap_open_live(dev, 65536, 1, 0, errbuf);
+ descr = pcap_open_live(dev, 65536, 1, 1, errbuf);
}
if (descr == NULL)
{
--- /dev/null
+TGT_PREREQS := libfreeradius-radius.a
+TGT_LDLIBS := $(LIBS) @PCAP_LIBS@
+
+SOURCES := radsniff.c
+
+ifneq ($(PCAP_LIBS),)
+TARGET := radsniff
+else
+TARGET :=
+endif
const char *radutmp_file = NULL;
int check_config = FALSE;
-char *radius_dir = NULL;
+const char *raddb_dir = NULL;
const char *radacct_dir = NULL;
const char *radlib_dir = NULL;
uint32_t myip = INADDR_ANY;
fprintf(output, " -d: set the raddb directory (default is %s)\n",
RADIUS_DIR);
fprintf(output, " -f: give fingerd output\n");
+ fprintf(output, " -F <file>: Use radutmp <file>\n");
fprintf(output, " -i: show session ID\n");
fprintf(output, " -n: no full name\n");
fprintf(output, " -N <nas-ip-address>: Show entries matching the given NAS IP address\n");
uint32_t nas_ip_address = INADDR_NONE;
int zap = 0;
- radius_dir = RADIUS_DIR;
+ raddb_dir = RADIUS_DIR;
- while((c = getopt(argc, argv, "d:fnN:sSipP:crRu:U:Z")) != EOF) switch(c) {
+ while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) {
case 'd':
- radius_dir = optarg;
+ raddb_dir = optarg;
break;
case 'f':
fingerd++;
showname = 0;
break;
+ case 'F':
+ radutmp_file = optarg;
+ break;
case 'h':
usage(0);
break;
exit(0); /* don't bother printing anything else */
}
+ if (radutmp_file) goto have_radutmp;
+
/*
* Initialize mainconfig
*/
mainconfig.radlog_dest = RADLOG_STDOUT;
/* Read radiusd.conf */
- snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
+ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir);
maincs = cf_file_read(buffer);
if (!maincs) {
fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
}
/* Read the radutmp section of radiusd.conf */
- cs = cf_section_sub_find(cf_section_sub_find(maincs, "modules"), "radutmp");
+ cs = cf_section_find_name2(cf_section_sub_find(maincs, "modules"), "radutmp", NULL);
if(!cs) {
fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
argv[0]);
/* Assign the correct path for the radutmp file */
radutmp_file = radutmpconfig.radutmp_fn;
+ have_radutmp:
/*
* See if we are "fingerd".
*/
} else if (strcasecmp(hs_check, "request") == 0) {
home->ping_check = HOME_PING_CHECK_REQUEST;
+ if (!home->ping_user_name ||
+ !*home->ping_user_name) {
+ cf_log_err(cf_sectiontoitem(cs), "You must supply a 'username' to enable status_check=request");
+ goto error;
+ }
+
+ if ((home->type == HOME_TYPE_AUTH) &&
+ (!home->ping_user_password ||
+ !*home->ping_user_password)) {
+ cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable status_check=request");
+ goto error;
+ }
+
} else {
cf_log_err(cf_sectiontoitem(cs),
- "Invalid ping_check \"%s\" for home server %s.",
+ "Invalid status__check \"%s\" for home server %s.",
hs_check, name2);
goto error;
}
if ((home->ping_check != HOME_PING_CHECK_NONE) &&
(home->ping_check != HOME_PING_CHECK_STATUS_SERVER)) {
if (!home->ping_user_name) {
- cf_log_err(cf_sectiontoitem(cs), "You must supply a user name to enable ping checks");
+ cf_log_err(cf_sectiontoitem(cs), "You must supply a user name to enable status_check=request");
goto error;
}
if ((home->type == HOME_TYPE_AUTH) &&
!home->ping_user_password) {
- cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable ping checks");
+ cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable status_check=request");
goto error;
}
}
return 0;
}
- if (!auth_pool || auth_pool_name &&
- (strcmp(auth_pool_name, acct_pool_name) != 0)) {
+ if (!auth_pool ||
+ (auth_pool_name &&
+ (strcmp(auth_pool_name, acct_pool_name) != 0))) {
do_print = TRUE;
}
#include <dispatch/dispatch.h>
#endif
#include <mach/task.h>
+#include <mach/mach_init.h>
#include <mach/semaphore.h>
#undef sem_t
#include <openssl/ocsp.h>
#endif
-#ifdef HAVE_PTHREAD_H
-#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
-#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
-#else
-#define PTHREAD_MUTEX_LOCK(_x)
-#define PTHREAD_MUTEX_UNLOCK(_x)
-#endif
-
-
/* record */
static void record_init(record_t *buf);
static void record_close(record_t *buf);
static unsigned int record_minus(record_t *buf, void *ptr,
unsigned int size);
+#ifdef PSK_MAX_IDENTITY_LEN
+static unsigned int psk_server_callback(SSL *ssl, const char *identity,
+ unsigned char *psk, int max_psk_len)
+{
+ unsigned int psk_len;
+ fr_tls_server_conf_t *conf;
+
+ conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl,
+ FR_TLS_EX_INDEX_CONF);
+ if (!conf) return 0;
+
+ /*
+ * FIXME: Look up the PSK password based on the identity!
+ */
+ if (strcmp(identity, conf->psk_identity) != 0) {
+ return 0;
+ }
+
+ psk_len = strlen(conf->psk_password);
+ if (psk_len > (2 * max_psk_len)) return 0;
+
+ return fr_hex2bin(conf->psk_password, psk, psk_len);
+}
+
+static unsigned int psk_client_callback(SSL *ssl, UNUSED const char *hint,
+ char *identity, unsigned int max_identity_len,
+ unsigned char *psk, unsigned int max_psk_len)
+{
+ unsigned int psk_len;
+ fr_tls_server_conf_t *conf;
+
+ conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl,
+ FR_TLS_EX_INDEX_CONF);
+ if (!conf) return 0;
+
+ psk_len = strlen(conf->psk_password);
+ if (psk_len > (2 * max_psk_len)) return 0;
+
+ strlcpy(identity, conf->psk_identity, max_identity_len);
+
+ return fr_hex2bin(conf->psk_password, psk, psk_len);
+}
+
+#endif
+
tls_session_t *tls_new_client_session(fr_tls_server_conf_t *conf, int fd)
{
int verify_mode;
offsetof(fr_tls_server_conf_t, ocsp_override_url), NULL, "no"},
{ "url", PW_TYPE_STRING_PTR,
offsetof(fr_tls_server_conf_t, ocsp_url), NULL, NULL },
+ { "use_nonce", PW_TYPE_BOOLEAN,
+ offsetof(fr_tls_server_conf_t, ocsp_use_nonce), NULL, "yes"},
+ { "timeout", PW_TYPE_INTEGER,
+ offsetof(fr_tls_server_conf_t, ocsp_timeout), NULL, "yes"},
+ { "softfail", PW_TYPE_BOOLEAN,
+ offsetof(fr_tls_server_conf_t, ocsp_softfail), NULL, "yes"},
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
#endif
offsetof(fr_tls_server_conf_t, ca_file), NULL, NULL },
{ "private_key_password", PW_TYPE_STRING_PTR,
offsetof(fr_tls_server_conf_t, private_key_password), NULL, NULL },
+#ifdef PSK_MAX_IDENTITY_LEN
+ { "psk_identity", PW_TYPE_STRING_PTR,
+ offsetof(fr_tls_server_conf_t, psk_identity), NULL, NULL },
+ { "psk_hexphrase", PW_TYPE_STRING_PTR,
+ offsetof(fr_tls_server_conf_t, psk_password), NULL, NULL },
+#endif
{ "dh_file", PW_TYPE_STRING_PTR,
offsetof(fr_tls_server_conf_t, dh_file), NULL, NULL },
{ "random_file", PW_TYPE_STRING_PTR,
static void cbtls_remove_session(UNUSED SSL_CTX *ctx, SSL_SESSION *sess)
{
- int i;
-
size_t size;
char buffer[2 * MAX_SESSION_SIZE + 1];
{
OCSP_CERTID *certid;
OCSP_REQUEST *req;
- OCSP_RESPONSE *resp;
+ OCSP_RESPONSE *resp = NULL;
OCSP_BASICRESP *bresp = NULL;
char *host = NULL;
char *port = NULL;
int status ;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
int reason;
+#if OPENSSL_VERSION_NUMBER >= 0x1000003f
+ OCSP_REQ_CTX *ctx;
+ int rc;
+ struct timeval now;
+ struct timeval when;
+#endif
/*
* Create OCSP Request
certid = OCSP_cert_to_id(NULL, client_cert, issuer_cert);
req = OCSP_REQUEST_new();
OCSP_request_add0_id(req, certid);
- OCSP_request_add1_nonce(req, NULL, 8);
+ if(conf->ocsp_use_nonce) {
+ OCSP_request_add1_nonce(req, NULL, 8);
+ }
/*
* Send OCSP Request and get OCSP Response
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_set_conn_port(cbio, port);
+#if OPENSSL_VERSION_NUMBER < 0x1000003f
BIO_do_connect(cbio);
-
+
/* Send OCSP request and wait for response */
resp = OCSP_sendreq_bio(cbio, path, req);
- if(resp==0) {
+ if (!resp) {
radlog(L_ERR, "Error: Couldn't get OCSP response");
+ ocsp_ok = 2;
+ goto ocsp_end;
+ }
+#else
+ if (conf->ocsp_timeout)
+ BIO_set_nbio(cbio, 1);
+
+ rc = BIO_do_connect(cbio);
+ if ((rc <= 0) && ((!conf->ocsp_timeout) || !BIO_should_retry(cbio))) {
+ radlog(L_ERR, "Error: Couldn't connect to OCSP responder");
+ ocsp_ok = 2;
goto ocsp_end;
}
+ ctx = OCSP_sendreq_new(cbio, path, req, -1);
+ if (!ctx) {
+ radlog(L_ERR, "Error: Couldn't send OCSP request");
+ ocsp_ok = 2;
+ goto ocsp_end;
+ }
+
+ gettimeofday(&when, NULL);
+ when.tv_sec += conf->ocsp_timeout;
+
+ do {
+ rc = OCSP_sendreq_nbio(&resp, ctx);
+ if (conf->ocsp_timeout) {
+ gettimeofday(&now, NULL);
+ if (!timercmp(&now, &when, <))
+ break;
+ }
+ } while ((rc == -1) && BIO_should_retry(cbio));
+
+ if (conf->ocsp_timeout && (rc == -1) && BIO_should_retry(cbio)) {
+ radlog(L_ERR, "Error: OCSP response timed out");
+ ocsp_ok = 2;
+ goto ocsp_end;
+ }
+
+ OCSP_REQ_CTX_free(ctx);
+
+ if (rc == 0) {
+ radlog(L_ERR, "Error: Couldn't get OCSP response");
+ ocsp_ok = 2;
+ goto ocsp_end;
+ }
+#endif
+
/* Verify OCSP response status */
status = OCSP_response_status(resp);
DEBUG2("[ocsp] --> Response status: %s",OCSP_response_status_str(status));
goto ocsp_end;
}
bresp = OCSP_response_get1_basic(resp);
- if(OCSP_check_nonce(req, bresp)!=1) {
+ if(conf->ocsp_use_nonce && OCSP_check_nonce(req, bresp)!=1) {
radlog(L_ERR, "Error: OCSP response has wrong nonce value");
goto ocsp_end;
}
BIO_free_all(cbio);
OCSP_BASICRESP_free(bresp);
- if (ocsp_ok) {
+ switch (ocsp_ok) {
+ case 1:
DEBUG2("[ocsp] --> Certificate is valid!");
- } else {
+ break;
+ case 2:
+ if (conf->ocsp_softfail) {
+ DEBUG2("[ocsp] --> Unable to check certificate; assuming valid.");
+ DEBUG2("[ocsp] --> Warning! This may be insecure.");
+ ocsp_ok = 1;
+ } else {
+ DEBUG2("[ocsp] --> Unable to check certificate; failing!");
+ ocsp_ok = 0;
+ }
+ break;
+ default:
DEBUG2("[ocsp] --> Certificate has been expired/revoked!");
+ break;
}
return ocsp_ok;
* - Load the Private key & the certificate
* - Set the Context options & Verify options
*/
-static SSL_CTX *init_tls_ctx(fr_tls_server_conf_t *conf)
+static SSL_CTX *init_tls_ctx(fr_tls_server_conf_t *conf, int client)
{
const SSL_METHOD *meth;
SSL_CTX *ctx;
SSL_CTX_set_default_passwd_cb(ctx, cbtls_password);
}
+#ifdef PSK_MAX_IDENTITY_LEN
+ if ((conf->psk_identity && !conf->psk_password) ||
+ (!conf->psk_identity && conf->psk_password) ||
+ (conf->psk_identity && !*conf->psk_identity) ||
+ (conf->psk_password && !*conf->psk_password)) {
+ radlog(L_ERR, "Invalid PSK Configuration: psk_identity or psk_password are empty");
+ return NULL;
+ }
+
+ if (conf->psk_identity) {
+ size_t psk_len, hex_len;
+ char buffer[PSK_MAX_PSK_LEN];
+
+ if (conf->certificate_file ||
+ conf->private_key_password || conf->private_key_file ||
+ conf->ca_file || conf->ca_path) {
+ radlog(L_ERR, "When PSKs are used, No certificate configuration is permitted");
+ return NULL;
+ }
+
+ if (client) {
+ SSL_CTX_set_psk_client_callback(ctx,
+ psk_client_callback);
+ } else {
+ SSL_CTX_set_psk_server_callback(ctx,
+ psk_server_callback);
+ }
+
+ psk_len = strlen(conf->psk_password);
+ if (strlen(conf->psk_password) > (2 * PSK_MAX_PSK_LEN)) {
+ radlog(L_ERR, "psk_hexphrase is too long (max %d)",
+ PSK_MAX_PSK_LEN);
+ return NULL;
+ }
+
+ hex_len = fr_hex2bin(conf->psk_password, buffer, psk_len);
+ if (psk_len != (2 * hex_len)) {
+ radlog(L_ERR, "psk_hexphrase is not all hex");
+ return NULL;
+ }
+
+ goto post_ca;
+ }
+#else
+ client = client; /* -Wunused */
+#endif
+
/*
* Load our keys and certificates
*
}
}
+#ifdef PSK_MAX_IDENTITY_LEN
+post_ca:
+#endif
+
/*
* Set ctx_options
*/
/*
* Initialize TLS
*/
- conf->ctx = init_tls_ctx(conf);
+ conf->ctx = init_tls_ctx(conf, 0);
if (conf->ctx == NULL) {
goto error;
}
/*
* Initialize TLS
*/
- conf->ctx = init_tls_ctx(conf);
+ conf->ctx = init_tls_ctx(conf, 1);
if (conf->ctx == NULL) {
goto error;
}
}
}
-static void dump_hex(const char *msg, const uint8_t *data, size_t data_len)
-{
- size_t i;
-
- if (debug_flag < 3) return;
-
- printf("%s %d\n", msg, (int) data_len);
- if (data_len > 256) data_len = 256;
-
- for (i = 0; i < data_len; i++) {
- if ((i & 0x0f) == 0x00) printf ("%02x: ", (unsigned int) i);
- printf("%02x ", data[i]);
- if ((i & 0x0f) == 0x0f) printf ("\n");
- }
- printf("\n");
- fflush(stdout);
-}
-
-static void tls_socket_close(rad_listen_t *listener)
-{
- listen_socket_t *sock = listener->data;
-
- listener->status = RAD_LISTEN_STATUS_REMOVE_FD;
- listener->tls = NULL; /* parent owns this! */
-
- if (sock->parent) {
- /*
- * Decrement the number of connections.
- */
- if (sock->parent->num_connections > 0) {
- sock->parent->num_connections--;
- }
- if (sock->client->num_connections > 0) {
- sock->client->num_connections--;
- }
- }
-
- /*
- * Tell the event handler that an FD has disappeared.
- */
- DEBUG("Client has closed connection");
- event_new_fd(listener);
-
- /*
- * Do NOT free the listener here. It's in use by
- * a request, and will need to hang around until
- * all of the requests are done.
- *
- * It is instead free'd in remove_from_request_hash()
- */
-}
-
-static int tls_socket_write(rad_listen_t *listener, REQUEST *request)
-{
- uint8_t *p;
- ssize_t rcode;
- listen_socket_t *sock = listener->data;
-
- p = sock->ssn->dirty_out.data;
-
- while (p < (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used)) {
- RDEBUG3("Writing to socket %d", request->packet->sockfd);
- rcode = write(request->packet->sockfd, p,
- (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used) - p);
- if (rcode <= 0) {
- RDEBUG("Error writing to TLS socket: %s", strerror(errno));
-
- tls_socket_close(listener);
- return 0;
- }
- p += rcode;
- }
-
- sock->ssn->dirty_out.used = 0;
-
- return 1;
-}
-
-
-static int tls_socket_recv(rad_listen_t *listener)
-{
- int doing_init = FALSE;
- ssize_t rcode;
- RADIUS_PACKET *packet;
- REQUEST *request;
- listen_socket_t *sock = listener->data;
- fr_tls_status_t status;
- RADCLIENT *client = sock->client;
-
- if (!sock->packet) {
- sock->packet = rad_alloc(0);
- if (!sock->packet) return 0;
-
- sock->packet->sockfd = listener->fd;
- sock->packet->src_ipaddr = sock->other_ipaddr;
- sock->packet->src_port = sock->other_port;
- sock->packet->dst_ipaddr = sock->my_ipaddr;
- sock->packet->dst_port = sock->my_port;
-
- if (sock->request) sock->request->packet = sock->packet;
- }
-
- /*
- * Allocate a REQUEST for debugging.
- */
- if (!sock->request) {
- sock->request = request = request_alloc();
- if (!sock->request) {
- radlog(L_ERR, "Out of memory");
- return 0;
- }
-
- rad_assert(request->packet == NULL);
- rad_assert(sock->packet != NULL);
- request->packet = sock->packet;
-
- request->component = "<core>";
- request->component = "<tls-connect>";
-
- /*
- * Not sure if we should do this on every packet...
- */
- request->reply = rad_alloc(0);
- if (!request->reply) return 0;
-
- request->options = RAD_REQUEST_OPTION_DEBUG2;
-
- rad_assert(sock->ssn == NULL);
-
- sock->ssn = tls_new_session(listener->tls, sock->request,
- listener->tls->require_client_cert);
- if (!sock->ssn) {
- request_free(&sock->request);
- sock->packet = NULL;
- return 0;
- }
-
- SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
- SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);
-
- doing_init = TRUE;
- }
-
- rad_assert(sock->request != NULL);
- rad_assert(sock->request->packet != NULL);
- rad_assert(sock->packet != NULL);
- rad_assert(sock->ssn != NULL);
-
- request = sock->request;
-
- RDEBUG3("Reading from socket %d", request->packet->sockfd);
- PTHREAD_MUTEX_LOCK(&sock->mutex);
- rcode = read(request->packet->sockfd,
- sock->ssn->dirty_in.data,
- sizeof(sock->ssn->dirty_in.data));
- if ((rcode < 0) && (errno == ECONNRESET)) {
- do_close:
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- tls_socket_close(listener);
- return 0;
- }
-
- if (rcode < 0) {
- RDEBUG("Error reading TLS socket: %s", strerror(errno));
- goto do_close;
- }
-
- /*
- * Normal socket close.
- */
- if (rcode == 0) goto do_close;
-
- sock->ssn->dirty_in.used = rcode;
- memset(sock->ssn->dirty_in.data + sock->ssn->dirty_in.used,
- 0, 16);
-
- dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);
-
- /*
- * Catch attempts to use non-SSL.
- */
- if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
- RDEBUG("Non-TLS data sent to TLS socket: closing");
- goto do_close;
- }
-
- /*
- * Skip ahead to reading application data.
- */
- if (SSL_is_init_finished(sock->ssn->ssl)) goto app;
-
- if (!tls_handshake_recv(request, sock->ssn)) {
- RDEBUG("FAILED in TLS handshake receive");
- goto do_close;
- }
-
- if (sock->ssn->dirty_out.used > 0) {
- tls_socket_write(listener, request);
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- return 0;
- }
-
-app:
- /*
- * FIXME: Run the packet through a virtual server in
- * order to see if we like the certificate presented by
- * the client.
- */
-
- status = tls_application_data(sock->ssn, request);
- RDEBUG("Application data status %d", status);
-
- if (status == FR_TLS_MORE_FRAGMENTS) {
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- return 0;
- }
-
- if (sock->ssn->clean_out.used == 0) {
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- return 0;
- }
-
- dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);
-
- /*
- * If the packet is a complete RADIUS packet, return it to
- * the caller. Otherwise...
- */
- if ((sock->ssn->clean_out.used < 20) ||
- (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
- RDEBUG("Received bad packet: Length %d contents %d",
- sock->ssn->clean_out.used,
- (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
- goto do_close;
- }
-
- packet = sock->packet;
- packet->data = rad_malloc(sock->ssn->clean_out.used);
- packet->data_len = sock->ssn->clean_out.used;
- record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
- packet->vps = NULL;
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
- if (!rad_packet_ok(packet, 0)) {
- RDEBUG("Received bad packet: %s", fr_strerror());
- tls_socket_close(listener);
- return 0; /* do_close unlocks the mutex */
- }
-
- /*
- * Copied from src/lib/radius.c, rad_recv();
- */
- if (fr_debug_flag) {
- char host_ipaddr[128];
-
- if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
- RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
- fr_packet_codes[packet->code],
- inet_ntop(packet->src_ipaddr.af,
- &packet->src_ipaddr.ipaddr,
- host_ipaddr, sizeof(host_ipaddr)),
- packet->src_port,
- packet->id, (int) packet->data_len);
- } else {
- RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
- inet_ntop(packet->src_ipaddr.af,
- &packet->src_ipaddr.ipaddr,
- host_ipaddr, sizeof(host_ipaddr)),
- packet->src_port,
- packet->code,
- packet->id, (int) packet->data_len);
- }
- }
-
- FR_STATS_INC(auth, total_requests);
-
- return 1;
-}
-
-
-int dual_tls_recv(rad_listen_t *listener)
-{
- RADIUS_PACKET *packet;
- REQUEST *request;
- RAD_REQUEST_FUNP fun = NULL;
- listen_socket_t *sock = listener->data;
- RADCLIENT *client = sock->client;
-
- if (!tls_socket_recv(listener)) {
- return 0;
- }
-
- rad_assert(sock->request != NULL);
- rad_assert(sock->request->packet != NULL);
- rad_assert(sock->packet != NULL);
- rad_assert(sock->ssn != NULL);
-
- request = sock->request;
- packet = sock->packet;
-
- /*
- * Some sanity checks, based on the packet code.
- */
- switch(packet->code) {
- case PW_AUTHENTICATION_REQUEST:
- if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
- FR_STATS_INC(auth, total_requests);
- fun = rad_authenticate;
- break;
-
- case PW_ACCOUNTING_REQUEST:
- if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
- FR_STATS_INC(acct, total_requests);
- fun = rad_accounting;
- break;
-
- case PW_STATUS_SERVER:
- if (!mainconfig.status_server) {
- FR_STATS_INC(auth, total_unknown_types);
- DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
- rad_free(&sock->packet);
- request->packet = NULL;
- return 0;
- }
- fun = rad_status_server;
- break;
-
- default:
- bad_packet:
- FR_STATS_INC(auth, total_unknown_types);
-
- DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
- packet->code, client->shortname, packet->src_port);
- rad_free(&sock->packet);
- request->packet = NULL;
- return 0;
- } /* switch over packet types */
-
- if (!request_receive(listener, packet, client, fun)) {
- FR_STATS_INC(auth, total_packets_dropped);
- rad_free(&sock->packet);
- request->packet = NULL;
- return 0;
- }
-
- sock->packet = NULL; /* we have no need for more partial reads */
- request->packet = NULL;
-
- return 1;
-}
-
-
-/*
- * Send a response packet
- */
-int dual_tls_send(rad_listen_t *listener, REQUEST *request)
-{
- listen_socket_t *sock = listener->data;
-
- rad_assert(request->listener == listener);
- rad_assert(listener->send == dual_tls_send);
-
- /*
- * Accounting reject's are silently dropped.
- *
- * We do it here to avoid polluting the rest of the
- * code with this knowledge
- */
- if (request->reply->code == 0) return 0;
-
- /*
- * Pack the VPs
- */
- if (rad_encode(request->reply, request->packet,
- request->client->secret) < 0) {
- RDEBUG("Failed encoding packet: %s", fr_strerror());
- return 0;
- }
-
- /*
- * Sign the packet.
- */
- if (rad_sign(request->reply, request->packet,
- request->client->secret) < 0) {
- RDEBUG("Failed signing packet: %s", fr_strerror());
- return 0;
- }
-
- PTHREAD_MUTEX_LOCK(&sock->mutex);
- /*
- * Write the packet to the SSL buffers.
- */
- record_plus(&sock->ssn->clean_in,
- request->reply->data, request->reply->data_len);
-
- /*
- * Do SSL magic to get encrypted data.
- */
- tls_handshake_send(request, sock->ssn);
-
- /*
- * And finally write the data to the socket.
- */
- if (sock->ssn->dirty_out.used > 0) {
- dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
-
- tls_socket_write(listener, request);
- }
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
- return 0;
-}
-
-
-int proxy_tls_recv(rad_listen_t *listener)
-{
- int rcode;
- size_t length;
- listen_socket_t *sock = listener->data;
- char buffer[256];
- uint8_t data[1024];
- RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
-
- DEBUG3("Proxy SSL socket has data to read");
- PTHREAD_MUTEX_LOCK(&sock->mutex);
-redo:
- rcode = SSL_read(sock->ssn->ssl, data, 4);
- if (rcode <= 0) {
- int err = SSL_get_error(sock->ssn->ssl, rcode);
- switch (err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- rcode = 0;
- goto redo;
- case SSL_ERROR_ZERO_RETURN:
- /* remote end sent close_notify, send one back */
- SSL_shutdown(sock->ssn->ssl);
-
- case SSL_ERROR_SYSCALL:
- do_close:
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- tls_socket_close(listener);
- return 0;
-
- default:
- while ((err = ERR_get_error())) {
- DEBUG("proxy recv says %s",
- ERR_error_string(err, NULL));
- }
-
- goto do_close;
- }
- }
-
- length = (data[2] << 8) | data[3];
- DEBUG3("Proxy received header saying we have a packet of %u bytes",
- (unsigned int) length);
-
- if (length > sizeof(data)) {
- DEBUG("Received packet will be too large! (%u)",
- (data[2] << 8) | data[3]);
- goto do_close;
- }
-
- rcode = SSL_read(sock->ssn->ssl, data + 4, length);
- if (rcode <= 0) {
- switch (SSL_get_error(sock->ssn->ssl, rcode)) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- rcode = 0;
- break;
-
- case SSL_ERROR_ZERO_RETURN:
- /* remote end sent close_notify, send one back */
- SSL_shutdown(sock->ssn->ssl);
- goto do_close;
- default:
- goto do_close;
- }
- }
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
- packet = rad_alloc(0);
- packet->sockfd = listener->fd;
- packet->src_ipaddr = sock->other_ipaddr;
- packet->src_port = sock->other_port;
- packet->dst_ipaddr = sock->my_ipaddr;
- packet->dst_port = sock->my_port;
- packet->code = data[0];
- packet->id = data[1];
- packet->data_len = length;
- packet->data = rad_malloc(packet->data_len);
- memcpy(packet->data, data, packet->data_len);
- memcpy(packet->vector, packet->data + 4, 16);
-
- /*
- * FIXME: Client MIB updates?
- */
- switch(packet->code) {
- case PW_AUTHENTICATION_ACK:
- case PW_ACCESS_CHALLENGE:
- case PW_AUTHENTICATION_REJECT:
- fun = rad_authenticate;
- break;
-
-#ifdef WITH_ACCOUNTING
- case PW_ACCOUNTING_RESPONSE:
- fun = rad_accounting;
- break;
-#endif
-
- default:
- /*
- * FIXME: Update MIB for packet types?
- */
- radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
- "from home server %s port %d - ID %d : IGNORED",
- packet->code,
- ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
- packet->src_port, packet->id);
- rad_free(&packet);
- return 0;
- }
-
- if (!request_proxy_reply(packet)) {
- rad_free(&packet);
- return 0;
- }
-
- return 1;
-}
-
-int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
-{
- int rcode;
- listen_socket_t *sock = listener->data;
-
- /*
- * Normal proxying calls us with the data already
- * encoded. The "ping home server" code does not. So,
- * if there's no packet, encode it here.
- */
- if (!request->proxy->data) {
- request->proxy_listener->encode(request->proxy_listener,
- request);
- }
-
- DEBUG3("Proxy is writing %u bytes to SSL",
- (unsigned int) request->proxy->data_len);
- PTHREAD_MUTEX_LOCK(&sock->mutex);
- while ((rcode = SSL_write(sock->ssn->ssl, request->proxy->data,
- request->proxy->data_len)) < 0) {
- int err;
- while ((err = ERR_get_error())) {
- DEBUG("proxy SSL_write says %s",
- ERR_error_string(err, NULL));
- }
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
- tls_socket_close(listener);
- return 0;
- }
- PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
- return 1;
-}
-
#endif /* WITH_TLS */
--- /dev/null
+/*
+ * tls.c
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/process.h>
+#include <freeradius-devel/rad_assert.h>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef WITH_TLS
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_OCSP_H
+#include <openssl/ocsp.h>
+#endif
+
+#ifdef HAVE_PTHREAD_H
+#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
+#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
+#else
+#define PTHREAD_MUTEX_LOCK(_x)
+#define PTHREAD_MUTEX_UNLOCK(_x)
+#endif
+
+static void dump_hex(const char *msg, const uint8_t *data, size_t data_len)
+{
+ size_t i;
+
+ if (debug_flag < 3) return;
+
+ printf("%s %d\n", msg, (int) data_len);
+ if (data_len > 256) data_len = 256;
+
+ for (i = 0; i < data_len; i++) {
+ if ((i & 0x0f) == 0x00) printf ("%02x: ", (unsigned int) i);
+ printf("%02x ", data[i]);
+ if ((i & 0x0f) == 0x0f) printf ("\n");
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+static void tls_socket_close(rad_listen_t *listener)
+{
+ listen_socket_t *sock = listener->data;
+
+ listener->status = RAD_LISTEN_STATUS_REMOVE_FD;
+ listener->tls = NULL; /* parent owns this! */
+
+ if (sock->parent) {
+ /*
+ * Decrement the number of connections.
+ */
+ if (sock->parent->num_connections > 0) {
+ sock->parent->num_connections--;
+ }
+ if (sock->client->num_connections > 0) {
+ sock->client->num_connections--;
+ }
+ }
+
+ /*
+ * Tell the event handler that an FD has disappeared.
+ */
+ DEBUG("Client has closed connection");
+ event_new_fd(listener);
+
+ /*
+ * Do NOT free the listener here. It's in use by
+ * a request, and will need to hang around until
+ * all of the requests are done.
+ *
+ * It is instead free'd in remove_from_request_hash()
+ */
+}
+
+static int tls_socket_write(rad_listen_t *listener, REQUEST *request)
+{
+ uint8_t *p;
+ ssize_t rcode;
+ listen_socket_t *sock = listener->data;
+
+ p = sock->ssn->dirty_out.data;
+
+ while (p < (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used)) {
+ RDEBUG3("Writing to socket %d", request->packet->sockfd);
+ rcode = write(request->packet->sockfd, p,
+ (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used) - p);
+ if (rcode <= 0) {
+ RDEBUG("Error writing to TLS socket: %s", strerror(errno));
+
+ tls_socket_close(listener);
+ return 0;
+ }
+ p += rcode;
+ }
+
+ sock->ssn->dirty_out.used = 0;
+
+ return 1;
+}
+
+
+static int tls_socket_recv(rad_listen_t *listener)
+{
+ int doing_init = FALSE;
+ ssize_t rcode;
+ RADIUS_PACKET *packet;
+ REQUEST *request;
+ listen_socket_t *sock = listener->data;
+ fr_tls_status_t status;
+ RADCLIENT *client = sock->client;
+
+ if (!sock->packet) {
+ sock->packet = rad_alloc(0);
+ if (!sock->packet) return 0;
+
+ sock->packet->sockfd = listener->fd;
+ sock->packet->src_ipaddr = sock->other_ipaddr;
+ sock->packet->src_port = sock->other_port;
+ sock->packet->dst_ipaddr = sock->my_ipaddr;
+ sock->packet->dst_port = sock->my_port;
+
+ if (sock->request) sock->request->packet = sock->packet;
+ }
+
+ /*
+ * Allocate a REQUEST for debugging.
+ */
+ if (!sock->request) {
+ sock->request = request = request_alloc();
+ if (!sock->request) {
+ radlog(L_ERR, "Out of memory");
+ return 0;
+ }
+
+ rad_assert(request->packet == NULL);
+ rad_assert(sock->packet != NULL);
+ request->packet = sock->packet;
+
+ request->component = "<core>";
+ request->component = "<tls-connect>";
+
+ /*
+ * Not sure if we should do this on every packet...
+ */
+ request->reply = rad_alloc(0);
+ if (!request->reply) return 0;
+
+ request->options = RAD_REQUEST_OPTION_DEBUG2;
+
+ rad_assert(sock->ssn == NULL);
+
+ sock->ssn = tls_new_session(listener->tls, sock->request,
+ listener->tls->require_client_cert);
+ if (!sock->ssn) {
+ request_free(&sock->request);
+ sock->packet = NULL;
+ return 0;
+ }
+
+ SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
+ SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);
+
+ doing_init = TRUE;
+ }
+
+ rad_assert(sock->request != NULL);
+ rad_assert(sock->request->packet != NULL);
+ rad_assert(sock->packet != NULL);
+ rad_assert(sock->ssn != NULL);
+
+ request = sock->request;
+
+ RDEBUG3("Reading from socket %d", request->packet->sockfd);
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+ rcode = read(request->packet->sockfd,
+ sock->ssn->dirty_in.data,
+ sizeof(sock->ssn->dirty_in.data));
+ if ((rcode < 0) && (errno == ECONNRESET)) {
+ do_close:
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ tls_socket_close(listener);
+ return 0;
+ }
+
+ if (rcode < 0) {
+ RDEBUG("Error reading TLS socket: %s", strerror(errno));
+ goto do_close;
+ }
+
+ /*
+ * Normal socket close.
+ */
+ if (rcode == 0) goto do_close;
+
+ sock->ssn->dirty_in.used = rcode;
+ memset(sock->ssn->dirty_in.data + sock->ssn->dirty_in.used,
+ 0, 16);
+
+ dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);
+
+ /*
+ * Catch attempts to use non-SSL.
+ */
+ if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
+ RDEBUG("Non-TLS data sent to TLS socket: closing");
+ goto do_close;
+ }
+
+ /*
+ * Skip ahead to reading application data.
+ */
+ if (SSL_is_init_finished(sock->ssn->ssl)) goto app;
+
+ if (!tls_handshake_recv(request, sock->ssn)) {
+ RDEBUG("FAILED in TLS handshake receive");
+ goto do_close;
+ }
+
+ if (sock->ssn->dirty_out.used > 0) {
+ tls_socket_write(listener, request);
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ return 0;
+ }
+
+app:
+ /*
+ * FIXME: Run the packet through a virtual server in
+ * order to see if we like the certificate presented by
+ * the client.
+ */
+
+ status = tls_application_data(sock->ssn, request);
+ RDEBUG("Application data status %d", status);
+
+ if (status == FR_TLS_MORE_FRAGMENTS) {
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ return 0;
+ }
+
+ if (sock->ssn->clean_out.used == 0) {
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ return 0;
+ }
+
+ dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);
+
+ /*
+ * If the packet is a complete RADIUS packet, return it to
+ * the caller. Otherwise...
+ */
+ if ((sock->ssn->clean_out.used < 20) ||
+ (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
+ RDEBUG("Received bad packet: Length %d contents %d",
+ sock->ssn->clean_out.used,
+ (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
+ goto do_close;
+ }
+
+ packet = sock->packet;
+ packet->data = rad_malloc(sock->ssn->clean_out.used);
+ packet->data_len = sock->ssn->clean_out.used;
+ sock->ssn->record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
+ packet->vps = NULL;
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+ if (!rad_packet_ok(packet, 0)) {
+ RDEBUG("Received bad packet: %s", fr_strerror());
+ tls_socket_close(listener);
+ return 0; /* do_close unlocks the mutex */
+ }
+
+ /*
+ * Copied from src/lib/radius.c, rad_recv();
+ */
+ if (fr_debug_flag) {
+ char host_ipaddr[128];
+
+ if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
+ RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
+ fr_packet_codes[packet->code],
+ inet_ntop(packet->src_ipaddr.af,
+ &packet->src_ipaddr.ipaddr,
+ host_ipaddr, sizeof(host_ipaddr)),
+ packet->src_port,
+ packet->id, (int) packet->data_len);
+ } else {
+ RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
+ inet_ntop(packet->src_ipaddr.af,
+ &packet->src_ipaddr.ipaddr,
+ host_ipaddr, sizeof(host_ipaddr)),
+ packet->src_port,
+ packet->code,
+ packet->id, (int) packet->data_len);
+ }
+ }
+
+ FR_STATS_INC(auth, total_requests);
+
+ return 1;
+}
+
+
+int dual_tls_recv(rad_listen_t *listener)
+{
+ RADIUS_PACKET *packet;
+ REQUEST *request;
+ RAD_REQUEST_FUNP fun = NULL;
+ listen_socket_t *sock = listener->data;
+ RADCLIENT *client = sock->client;
+
+ if (!tls_socket_recv(listener)) {
+ return 0;
+ }
+
+ rad_assert(sock->request != NULL);
+ rad_assert(sock->request->packet != NULL);
+ rad_assert(sock->packet != NULL);
+ rad_assert(sock->ssn != NULL);
+
+ request = sock->request;
+ packet = sock->packet;
+
+ /*
+ * Some sanity checks, based on the packet code.
+ */
+ switch(packet->code) {
+ case PW_AUTHENTICATION_REQUEST:
+ if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
+ FR_STATS_INC(auth, total_requests);
+ fun = rad_authenticate;
+ break;
+
+ case PW_ACCOUNTING_REQUEST:
+ if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
+ FR_STATS_INC(acct, total_requests);
+ fun = rad_accounting;
+ break;
+
+ case PW_STATUS_SERVER:
+ if (!mainconfig.status_server) {
+ FR_STATS_INC(auth, total_unknown_types);
+ DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+ rad_free(&sock->packet);
+ request->packet = NULL;
+ return 0;
+ }
+ fun = rad_status_server;
+ break;
+
+ default:
+ bad_packet:
+ FR_STATS_INC(auth, total_unknown_types);
+
+ DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
+ packet->code, client->shortname, packet->src_port);
+ rad_free(&sock->packet);
+ request->packet = NULL;
+ return 0;
+ } /* switch over packet types */
+
+ if (!request_receive(listener, packet, client, fun)) {
+ FR_STATS_INC(auth, total_packets_dropped);
+ rad_free(&sock->packet);
+ request->packet = NULL;
+ return 0;
+ }
+
+ sock->packet = NULL; /* we have no need for more partial reads */
+ request->packet = NULL;
+
+ return 1;
+}
+
+
+/*
+ * Send a response packet
+ */
+int dual_tls_send(rad_listen_t *listener, REQUEST *request)
+{
+ listen_socket_t *sock = listener->data;
+
+ rad_assert(request->listener == listener);
+ rad_assert(listener->send == dual_tls_send);
+
+ /*
+ * Accounting reject's are silently dropped.
+ *
+ * We do it here to avoid polluting the rest of the
+ * code with this knowledge
+ */
+ if (request->reply->code == 0) return 0;
+
+ /*
+ * Pack the VPs
+ */
+ if (rad_encode(request->reply, request->packet,
+ request->client->secret) < 0) {
+ RDEBUG("Failed encoding packet: %s", fr_strerror());
+ return 0;
+ }
+
+ /*
+ * Sign the packet.
+ */
+ if (rad_sign(request->reply, request->packet,
+ request->client->secret) < 0) {
+ RDEBUG("Failed signing packet: %s", fr_strerror());
+ return 0;
+ }
+
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+ /*
+ * Write the packet to the SSL buffers.
+ */
+ sock->ssn->record_plus(&sock->ssn->clean_in,
+ request->reply->data, request->reply->data_len);
+
+ /*
+ * Do SSL magic to get encrypted data.
+ */
+ tls_handshake_send(request, sock->ssn);
+
+ /*
+ * And finally write the data to the socket.
+ */
+ if (sock->ssn->dirty_out.used > 0) {
+ dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
+
+ tls_socket_write(listener, request);
+ }
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+ return 0;
+}
+
+
+int proxy_tls_recv(rad_listen_t *listener)
+{
+ int rcode;
+ size_t length;
+ listen_socket_t *sock = listener->data;
+ char buffer[256];
+ uint8_t data[1024];
+ RADIUS_PACKET *packet;
+ RAD_REQUEST_FUNP fun = NULL;
+
+ DEBUG3("Proxy SSL socket has data to read");
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+redo:
+ rcode = SSL_read(sock->ssn->ssl, data, 4);
+ if (rcode <= 0) {
+ int err = SSL_get_error(sock->ssn->ssl, rcode);
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ rcode = 0;
+ goto redo;
+ case SSL_ERROR_ZERO_RETURN:
+ /* remote end sent close_notify, send one back */
+ SSL_shutdown(sock->ssn->ssl);
+
+ case SSL_ERROR_SYSCALL:
+ do_close:
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ tls_socket_close(listener);
+ return 0;
+
+ default:
+ while ((err = ERR_get_error())) {
+ DEBUG("proxy recv says %s",
+ ERR_error_string(err, NULL));
+ }
+
+ goto do_close;
+ }
+ }
+
+ length = (data[2] << 8) | data[3];
+ DEBUG3("Proxy received header saying we have a packet of %u bytes",
+ (unsigned int) length);
+
+ if (length > sizeof(data)) {
+ DEBUG("Received packet will be too large! (%u)",
+ (data[2] << 8) | data[3]);
+ goto do_close;
+ }
+
+ rcode = SSL_read(sock->ssn->ssl, data + 4, length);
+ if (rcode <= 0) {
+ switch (SSL_get_error(sock->ssn->ssl, rcode)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ rcode = 0;
+ break;
+
+ case SSL_ERROR_ZERO_RETURN:
+ /* remote end sent close_notify, send one back */
+ SSL_shutdown(sock->ssn->ssl);
+ goto do_close;
+ default:
+ goto do_close;
+ }
+ }
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+ packet = rad_alloc(0);
+ packet->sockfd = listener->fd;
+ packet->src_ipaddr = sock->other_ipaddr;
+ packet->src_port = sock->other_port;
+ packet->dst_ipaddr = sock->my_ipaddr;
+ packet->dst_port = sock->my_port;
+ packet->code = data[0];
+ packet->id = data[1];
+ packet->data_len = length;
+ packet->data = rad_malloc(packet->data_len);
+ memcpy(packet->data, data, packet->data_len);
+ memcpy(packet->vector, packet->data + 4, 16);
+
+ /*
+ * FIXME: Client MIB updates?
+ */
+ switch(packet->code) {
+ case PW_AUTHENTICATION_ACK:
+ case PW_ACCESS_CHALLENGE:
+ case PW_AUTHENTICATION_REJECT:
+ fun = rad_authenticate;
+ break;
+
+#ifdef WITH_ACCOUNTING
+ case PW_ACCOUNTING_RESPONSE:
+ fun = rad_accounting;
+ break;
+#endif
+
+ default:
+ /*
+ * FIXME: Update MIB for packet types?
+ */
+ radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
+ "from home server %s port %d - ID %d : IGNORED",
+ packet->code,
+ ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
+ packet->src_port, packet->id);
+ rad_free(&packet);
+ return 0;
+ }
+
+ if (!request_proxy_reply(packet)) {
+ rad_free(&packet);
+ return 0;
+ }
+
+ return 1;
+}
+
+int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
+{
+ int rcode;
+ listen_socket_t *sock = listener->data;
+
+ /*
+ * Normal proxying calls us with the data already
+ * encoded. The "ping home server" code does not. So,
+ * if there's no packet, encode it here.
+ */
+ if (!request->proxy->data) {
+ request->proxy_listener->encode(request->proxy_listener,
+ request);
+ }
+
+ DEBUG3("Proxy is writing %u bytes to SSL",
+ (unsigned int) request->proxy->data_len);
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+ while ((rcode = SSL_write(sock->ssn->ssl, request->proxy->data,
+ request->proxy->data_len)) < 0) {
+ int err;
+ while ((err = ERR_get_error())) {
+ DEBUG("proxy SSL_write says %s",
+ ERR_error_string(err, NULL));
+ }
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ tls_socket_close(listener);
+ return 0;
+ }
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+ return 1;
+}
+
+#endif /* WITH_TLS */
*/
fake->server = request->server;
- fake->packet = rad_alloc(0);
+ fake->packet = rad_alloc(1);
if (!fake->packet) {
request_free(&fake);
return NULL;
--- /dev/null
+SUBMAKEFILES := $(wildcard ${top_srcdir}/src/modules/rlm_*/all.mk)
--- /dev/null
+SOURCES := rlm_acct_unique.c
+
+TARGET := rlm_acct_unique.a
--- /dev/null
+TARGET := rlm_acctlog.a
+
+SOURCES := rlm_acctlog.c
--- /dev/null
+TARGET := rlm_always.a
+
+SOURCES := rlm_always.c
--- /dev/null
+TARGET = rlm_attr_filter.a
+SOURCES = rlm_attr_filter.c
--- /dev/null
+TARGET = rlm_attr_rewrite.a
+SOURCES = rlm_attr_rewrite.c
--- /dev/null
+SOURCES := rlm_chap.c
+
+TARGET := rlm_chap.a
--- /dev/null
+TARGET = rlm_checkval.a
+SOURCES = rlm_checkval.c
--- /dev/null
+TARGET = rlm_copy_packet.a
+SOURCES = rlm_copy_packet.c
--- /dev/null
+TARGET =
+SOURCES = rlm_counter.c
--- /dev/null
+TARGET = rlm_cram.a
+SOURCES = rlm_cram.c
rlm_dbm_install: rlm_dbm_cat rlm_dbm_parser
$(INSTALL) -m 644 rlm_dbm_cat.8 $(R)$(mandir)/man8
- $(INSTALL) -m 644 rlm_dbm_parse.8 $(R)$(mandir)/man8
+ $(INSTALL) -m 644 rlm_dbm_parser.8 $(R)$(mandir)/man8
--- /dev/null
+TARGET =
+SOURCES = rlm_dbm.c
-.TH RLM_DBM_PARSE 8
+.TH RLM_DBM_PARSER 8
.SH NAME
-rlm_dbm_parse - transforms simple syntax into rlm_dbm format
+rlm_dbm_parser - transforms simple syntax into rlm_dbm format
.SH SYNOPSIS
-.B rlm_dbm_parse
+.B rlm_dbm_parser
.RB [ \-c ]
.RB [ \-d
.IR raddb ]
.IR outputfile ]
.RB [ \-x ]
.RB [ \-v ]
-.RB [ \-q ]
+.RB [ \-q ]
[\fIusername ...\fP]
.SH DESCRIPTION
-\fBrlm_dbm_parse\fP reads a file of the syntax defined below, and writes
+\fBrlm_dbm_parser\fP reads a file of the syntax defined below, and writes
a database file usable by rlm_dbm or edits current database.
.PP
.SH INPUT FORMAT
-\fIrlm_dbm_parse\fP reads a format similar to the one used by the files
+\fIrlm_dbm_parser\fP reads a format similar to the one used by the files
module. In incomplete RFC2234 ABNF, it looks like this:
.nf
--- /dev/null
+TARGET = rlm_detail.a
+SOURCES = rlm_detail.c
#include <fnmatch.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
#define DIRLEN 8192
struct detail_instance {
/* detail file permissions */
int detailperm;
+ /* detail file group */
+ char *group;
+
/* directory permissions */
int dirperm;
offsetof(struct detail_instance,header), NULL, "%t" },
{ "detailperm", PW_TYPE_INTEGER,
offsetof(struct detail_instance,detailperm), NULL, "0600" },
+ { "group", PW_TYPE_STRING_PTR,
+ offsetof(struct detail_instance,group), NULL, NULL},
{ "dirperm", PW_TYPE_INTEGER,
offsetof(struct detail_instance,dirperm), NULL, "0755" },
{ "locking", PW_TYPE_BOOLEAN,
off_t fsize;
FILE *fp;
+#ifdef HAVE_GRP_H
+ gid_t gid;
+ struct group *grp;
+ char *endptr;
+#endif
+
struct detail_instance *inst = instance;
rad_assert(request != NULL);
return RLM_MODULE_FAIL;
}
+
+#ifdef HAVE_GRP_H
+ if (inst->group != NULL) {
+ gid = strtol(inst->group, &endptr, 10);
+ if (*endptr != '\0') {
+ grp = getgrnam(inst->group);
+ if (grp == NULL) {
+ RDEBUG2("rlm_detail: Unable to find system group \"%s\"", inst->group);
+ goto skip_group;
+ }
+ gid = grp->gr_gid;
+ }
+
+ if (chown(buffer, -1, gid) == -1) {
+ RDEBUG2("rlm_detail: Unable to change system group of \"%s\"", buffer);
+ }
+ }
+
+ skip_group:
+#endif
+
/*
* Post a timestamp
*/
--- /dev/null
+TARGET = rlm_digest.a
+SOURCES = rlm_digest.c
--- /dev/null
+TARGET = rlm_dynamic_clients.a
+SOURCES = rlm_dynamic_clients.c
TARGET = @targetname@
SRCS = rlm_eap.c eap.c mem.c
HEADERS = eap.h rlm_eap.h
-RLM_CFLAGS = $(INCLTDL) -Ilibeap
+RLM_CFLAGS = -Ilibeap
CLIENTLIBS = libeap/$(LIBPREFIX)freeradius-eap.la $(LIBRADIUS)
RLM_LIBS = libeap/$(LIBPREFIX)freeradius-eap.la $(LIBLTDL)
RLM_INSTALL = install-subdirs
$(LT_OBJS): $(HEADERS)
-radeapclient: radeapclient.lo $(CLIENTLIBS)
+## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET.
+# This needs to be before the radeapclient rule, as the lhs $(EXEECT)
+# expansion is done as soon as the Makefile is loaded
+include ../rules.mak
+
+radeapclient$(EXEEXT): radeapclient.lo $(CLIENTLIBS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) -o radeapclient radeapclient.lo $(LIBRADIUS) $(CLIENTLIBS) $(LIBS) $(OPENSSL_LIBS)
radeapclient.lo: radeapclient.c $(HEADERS)
@$(MAKE) $(MFLAGS) X=$(X)rlm_eap/ -C $@ $(WHAT_TO_MAKE)
libeap/$(LIBPREFIX)freeradius-eap.la: libeap
-
-## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET.
-include ../rules.mak
--- /dev/null
+SUBMAKEFILES := libeap/all.mk rlm_eap.mk types/all.mk radeapclient.mk
--- /dev/null
+TARGET := libfreeradius-eap.a
+
+SOURCES := eapcommon.c eapcrypto.c eapsimlib.c fips186prf.c
+ifneq (${OPENSSL_LIBS},)
+SOURCES += eap_tls.c mppe_keys.c
+endif
+
+SRC_CFLAGS := -DEAPLIB $(OPENSSL_INCLUDE)
+
+SRC_INCDIRS := . ..
uint8_t data[1];
} eap_packet_t;
+/*
+ * Structure to represent eap channel binding packet format *on wire*
+ */
+typedef struct eap_chbind_packet_t {
+ uint8_t code;
+ uint8_t data[1];
+} eap_chbind_packet_t;
+
/*
* interfaces in eapcommon.c
extern int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply);
extern VALUE_PAIR *eap_packet2vp(const eap_packet_t *reply);
extern eap_packet_t *eap_vp2packet(VALUE_PAIR *vps);
+extern VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len);
+extern size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **packet);
#endif /* _EAP_TYPES_H */
return eap_packet;
}
+
+VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len)
+{
+ size_t size;
+ const uint8_t *ptr;
+ VALUE_PAIR *head = NULL;
+ VALUE_PAIR **tail = &head;
+ VALUE_PAIR *vp;
+
+ ptr = (const uint8_t *) packet;
+
+ do {
+ size = len;
+ if (size > 247) size = 247;
+
+ vp = paircreate(PW_VENDOR_SPECIFIC, VENDORPEC_UKERNA,
+ PW_TYPE_OCTETS);
+ if (!vp) {
+ pairfree(&head);
+ return NULL;
+ }
+ vp->vp_octets[0] = PW_UKERNA_CHBIND;
+ vp->vp_octets[1] = size;
+ memcpy(&vp->vp_octets[2], ptr, size);
+ vp->length = size + 2;
+
+ *tail = vp;
+ tail = &(vp->next);
+
+ ptr += size;
+ len -= size;
+ } while (len > 0);
+
+ return head;
+}
+
+
+/*
+ * Find the next EAP-CHANNEL-BINDING message in the
+ * pair list
+ */
+static VALUE_PAIR *eap_chbind_find_pair(VALUE_PAIR *vps)
+{
+ VALUE_PAIR *result = pairfind(vps, PW_VENDOR_SPECIFIC,
+ VENDORPEC_UKERNA);
+ while (result && (result->vp_octets[0] != PW_UKERNA_CHBIND))
+ result = result->next;
+ return result;
+}
+
+/*
+ * Handles multiple EAP-channel-binding Message attrs
+ * ie concatenates all to get the complete EAP-channel-binding packet.
+ */
+size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **result)
+{
+ VALUE_PAIR *first, *vp;
+ eap_chbind_packet_t *eap_chbind_packet;
+ unsigned char *ptr;
+ size_t len;
+
+ first = eap_chbind_find_pair(vps);
+
+ /*
+ * Sanity check the length, BEFORE malloc'ing memory.
+ */
+ len = 0;
+ for (vp = first; vp; vp = eap_chbind_find_pair(vp)) {
+ if ((vp->length < 2) ||
+ (vp->length != vp->vp_octets[1]+2)) {
+ DEBUG("rlm_eap: Malformed EAP channel binding value pair. Length in pair header does not match actual length");
+ return 0;
+ }
+ len += vp->vp_octets[1];
+ }
+
+ /*
+ * Now that we know the lengths are OK, allocate memory.
+ */
+ eap_chbind_packet = (eap_chbind_packet_t *) malloc(len);
+ if (eap_chbind_packet == NULL) {
+ radlog(L_ERR, "rlm_eap: out of memory");
+ return 0;
+ }
+
+ /*
+ * Copy the data from EAP-Message's over to our EAP packet.
+ */
+ ptr = (unsigned char *)eap_chbind_packet;
+
+ /* RADIUS ensures order of attrs, so just concatenate all */
+ for (vp = first; vp; vp = eap_chbind_find_pair(vp->next)) {
+ memcpy(ptr, vp->vp_octets+2, vp->length-2);
+ ptr += vp->length-2;
+ }
+
+ *result = eap_chbind_packet;
+ return len;
+}
#ifdef WITH_TLS
#include <freeradius-devel/tls.h>
-
-int tls_success(UNUSED tls_session_t *ssn, UNUSED REQUEST *request){return 0;}
-void tls_fail(UNUSED tls_session_t *ssn){_exit(1);}
-fr_tls_status_t tls_ack_handler(UNUSED tls_session_t *tls_session, UNUSED REQUEST *request){return FR_TLS_INVALID;}
-fr_tls_status_t tls_application_data(UNUSED tls_session_t *ssn, UNUSED REQUEST *request){return FR_TLS_INVALID;}
#endif
radlog_dest_t radlog_dest = RADLOG_STDERR;
--- /dev/null
+TARGET :=
+SOURCES := radeapclient.c
+
+ifneq ($(OPENSSL_LIBS),)
+SOURCES += ${top_srcdir}/src/main/cb.c ${top_srcdir}/src/main/tls.c
+endif
+
+TGT_PREREQS := libfreeradius-radius.a libfreeradius-eap.a
+TGT_PRLIBS := ${OPENSSL_LIBS} ${LIBS}
+
+SRC_INCDIRS := libeap
--- /dev/null
+TARGET := rlm_eap.a
+
+SOURCES := rlm_eap.c eap.c mem.c
+
+SRC_INCDIRS := . libeap
+
+# FIXME: This target is "phony", which means that every "make"
+# re-builds rlm_eap. We need to re-write this to be the name
+# of the ${BUILD_DIR}/.../filename!
+#TGT_PREREQS := libfreeradius-eap.a
--- /dev/null
+SUBMAKEFILES := $(wildcard ${top_srcdir}/src/modules/rlm_eap/types/rlm_eap_*/all.mk)
TARGET = rlm_eap_gtc
SRCS = rlm_eap_gtc.c
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS = -I../.. -I../../libeap
HEADERS = ../../rlm_eap.h ../../eap.h
RLM_INSTALL =
--- /dev/null
+TARGET := rlm_eap_gtc.a
+SOURCES := rlm_eap_gtc.c
+
+SRC_INCDIRS := ../.. ../../libeap
SRCS = logging_impl.c \
rlm_eap_ikev2.c \
ike_conf.c
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ikev2_cflags@
+RLM_CFLAGS = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ikev2_cflags@
RLM_LDFLAGS = @LDFLAGS@ @LIBS@ $(OPENSSL_LIBS)
HEADERS = eap_ikev2.h logging_impl.h ike_conf.h
RLM_INSTALL =
TARGET = rlm_eap_leap
SRCS = rlm_eap_leap.c eap_leap.c smbdes.c
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS = -I../.. -I../../libeap
HEADERS = eap_leap.h ../../eap.h ../../rlm_eap.h
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_eap_leap.a
+SOURCES = rlm_eap_leap.c eap_leap.c smbdes.c
+SRC_INCDIRS = ../.. ../../libeap
+HEADERS = eap_leap.h ../../eap.h ../../rlm_eap.h
TARGET = rlm_eap_md5
SRCS = rlm_eap_md5.c eap_md5.c
HEADERS = eap_md5.h
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS = -I../.. -I../../libeap
RLM_INSTALL =
RLM_DIR=../../
--- /dev/null
+TARGET := rlm_eap_md5.a
+SOURCES := rlm_eap_md5.c eap_md5.c
+HEADERS = eap_md5.h
+
+SRC_INCDIRS := ../.. ../../libeap
TARGET = rlm_eap_mschapv2
SRCS = rlm_eap_mschapv2.c
HEADERS = eap_mschapv2.h
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS = -I../.. -I../../libeap
RLM_INSTALL =
RLM_DIR=../../
--- /dev/null
+TARGET = rlm_eap_mschapv2.a
+SOURCES = rlm_eap_mschapv2.c
+SRC_INCDIRS = ../.. ../../libeap
/*
* Sanity check the response.
*/
- if (eap_ds->response->length <= 4) {
+ if (eap_ds->response->length <= 5) {
radlog(L_ERR, "rlm_eap_mschapv2: corrupted data");
return 0;
}
* issues a re-try, we will know which
* challenge value that they used.
*/
- n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf);
+ n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf[0]);
if (n == 3) {
DEBUG2(" Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s", err, retry, buf);
fr_hex2bin(buf, data->challenge, 16);
TARGET = @targetname@
SRCS = rlm_eap_peap.c peap.c
HEADERS = eap_peap.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_peap_cflags@
+RLM_CFLAGS = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_peap_cflags@
RLM_LIBS = @eap_peap_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_eap_peap.a
+SOURCES = rlm_eap_peap.c peap.c
+SRC_INCDIRS = ../.. ../../libeap
+TGT_LDLIBS = $(OPENSSL_INCLUDE)
+TGT_LDLIBS = $(OPENSSL_LIBS)
+#TGT_PREREQS = libfreeradius-eap.a
*/
case PEAP_STATUS_PHASE2_INIT: {
- int len = t->username->length + EAP_HEADER_LEN + 1;
+ size_t len = t->username->length + EAP_HEADER_LEN + 1;
t->status = PEAP_STATUS_PHASE2;
TARGET = rlm_eap_sim
SRCS = rlm_eap_sim.c
HEADERS =
-RLM_CFLAGS = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS = -I../.. -I../../libeap
RLM_LIBS = ../../libeap/$(LIBPREFIX)freeradius-eap.la
RLM_INSTALL =
TARGET = @targetname@
SRCS = rlm_eap_tls.c
HEADERS = rlm_eap_tls.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_tls_cflags@
+RLM_CFLAGS = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_tls_cflags@
RLM_LIBS = @eap_tls_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_eap_tls.a
+SOURCES = rlm_eap_tls.c
+SRC_INCDIRS = ../.. ../../libeap
+SRC_CFLAGS = $(OPENSSL_INCLUDE)
+TGT_LDLIBS = $(OPENSSL_LIBS)
+#TGT_PREREQS = libfreeradius-eap.a
/*
* Do authentication, by letting EAP-TLS do most of the work.
*/
-static int eaptls_authenticate(void *arg, EAP_HANDLER *handler)
+static int eaptls_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
{
fr_tls_status_t status;
tls_session_t *tls_session = (tls_session_t *) handler->opaque;
REQUEST *request = handler->request;
- fr_tls_server_conf_t *inst = arg;
RDEBUG2("Authenticate");
TARGET = @targetname@
SRCS = rlm_eap_tnc.c eap_tnc.c tncs_connect.c
HEADERS = eap_tnc.h tncs.h tncs_connect.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_tnc_cflags@
+RLM_CFLAGS = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_tnc_cflags@
RLM_LIBS = @eap_tnc_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
RLM_INSTALL =
TARGET = @targetname@
SRCS = rlm_eap_ttls.c ttls.c
HEADERS = eap_ttls.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_ttls_cflags@
+RLM_CFLAGS = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ttls_cflags@
RLM_LIBS = @eap_ttls_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_eap_ttls.a
+SOURCES = rlm_eap_ttls.c ttls.c
+SRC_INCDIRS = ../.. ../../libeap
+TGT_LDLIBS = $(OPENSSL_INCLUDE)
+TGT_LDLIBS = $(OPENSSL_LIBS)
+#TGT_PREREQS = libfreeradius-eap.a
const uint8_t *data;
size_t data_len;
REQUEST *request = handler->request;
+ eap_chbind_packet_t *chbind_packet;
+ size_t chbind_len;
rad_assert(request != NULL);
}
/*
+ * Process channel binding here.
+ */
+ chbind_len = eap_chbind_vp2packet(fake->packet->vps, &chbind_packet);
+ if (chbind_len > 0) {
+ /*CHBIND_REQ *req = chbind_allocate();
+ req->chbind_req = chbind_packet;
+ req->chbind_req_len = chbind_len;
+ if (fake->username) {
+ req->username = fake->username->vp_octets;
+ req->username_len = fake->username->length;
+ } else {
+ req->username = NULL;
+ req->username_len = 0;
+ }
+ chbind_process(request, req);
+ */
+
+ /* free the chbind packet; we're done with it */
+ free(chbind_packet);
+
+ /* encapsulate response here */
+ /*pairadd(replyvps, eap_chbind_packet2vp(req->chbind_resp,
+ req->chbind_resp_len));
+ */
+
+ /* clean up chbind req */
+ /*chbind_free(req);*/
+ }
+
+ /*
* Call authentication recursively, which will
* do PAP, CHAP, MS-CHAP, etc.
*/
TARGET =
SRCS = rlm_eap2.c
HEADERS =
-RLM_CFLAGS = $(INCLTDL) -I$(HOSTAP)/src/eap_common \
+RLM_CFLAGS = -I$(HOSTAP)/src/eap_common \
-I$(HOSTAP)/src/eap_server -I$(HOSTAP)/src \
-I$(HOSTAP)/src/common -I$(HOSTAP)/src/utils
RLM_LIBS = $(HOSTAP)/eap_example/libeap.so
--- /dev/null
+TARGET =
+SOURCES = rlm_eap2.c
+## this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
--- /dev/null
+TARGET = rlm_exec.a
+SOURCES = rlm_exec.c
--- /dev/null
+TARGET = rlm_expiration.a
+SOURCES = rlm_expiration.c
--- /dev/null
+TARGET = rlm_expr.a
+SOURCES = rlm_expr.c paircmp.c
char *out, size_t outlen,
RADIUS_ESCAPE_STRING func)
{
- int rcode;
int64_t result;
rlm_expr_t *inst = instance;
char buffer[256];
--- /dev/null
+TARGET = rlm_fastusers.a
+SOURCES = rlm_fastusers.c
--- /dev/null
+TARGET = rlm_files.a
+SOURCES = rlm_files.c
$(LT_OBJS): $(HEADERS)
-rlm_ippool_tool: rlm_ippool_tool.lo $(LIBRADIUS)
+rlm_ippool_tool$(EXEEXT): rlm_ippool_tool.lo $(LIBRADIUS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) \
-o $@ $^ $(RLM_LIBS) $(LIBS)
--- /dev/null
+TARGET =
+SOURCES = rlm_ippool.c
--- /dev/null
+TARGET = rlm_jradius.a
+SOURCES = rlm_jradius.c
+## this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
--- /dev/null
+TARGETNAME = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET = $(TARGETNAME).a
+endif
+
+SOURCES = rlm_krb5.c
+
+SRC_CFLAGS = @krb5_cflags@
+TGT_LDLIBS = @krb5_ldflags@
+
+SRC_CFLAGS += -I/usr/include/et -DKRB5_DEPRECATED
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files Makefile"
+ ac_config_files="$ac_config_files Makefile all.mk"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
AC_SUBST(krb5_ldflags)
AC_SUBST(targetname)
AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
--- /dev/null
+TARGETNAME = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET = $(TARGETNAME).a
+endif
+
+SOURCES = rlm_ldap.c @edir@
+
+SRC_CFLAGS = @ldap_cflags@
+TGT_LDLIBS = @ldap_ldflags@
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files Makefile"
+ ac_config_files="$ac_config_files Makefile all.mk"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
AC_SUBST(ldap_cflags)
AC_SUBST(targetname)
AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
--- /dev/null
+TARGET = rlm_linelog.a
+SOURCES = rlm_linelog.c
#include <fcntl.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
CONF_SECTION *cs;
char *filename;
int permissions;
+ char *group;
char *line;
char *reference;
} rlm_linelog_t;
offsetof(rlm_linelog_t,filename), NULL, NULL},
{ "permissions", PW_TYPE_INTEGER,
offsetof(rlm_linelog_t,permissions), NULL, "0600"},
+ { "group", PW_TYPE_STRING_PTR,
+ offsetof(rlm_linelog_t,group), NULL, NULL},
{ "format", PW_TYPE_STRING_PTR,
offsetof(rlm_linelog_t,line), NULL, NULL},
{ "reference", PW_TYPE_STRING_PTR,
rlm_linelog_t *inst = (rlm_linelog_t*) instance;
const char *value = inst->line;
+#ifdef HAVE_GRP_H
+ gid_t gid;
+ struct group *grp;
+ char *endptr;
+#endif
+
if (inst->reference) {
CONF_ITEM *ci;
CONF_PAIR *cp;
}
}
+#ifdef HAVE_GRP_H
+ if (inst->group != NULL) {
+ gid = strtol(inst->group, &endptr, 10);
+ if (*endptr != '\0') {
+ grp = getgrnam(inst->group);
+ if (grp == NULL) {
+ RDEBUG2("Unable to find system group \"%s\"", inst->group);
+ goto skip_group;
+ }
+ gid = grp->gr_gid;
+ }
+
+ if (chown(buffer, -1, gid) == -1) {
+ RDEBUG2("Unable to change system group of \"%s\"", buffer);
+ }
+ }
+
+ skip_group:
+#endif
+
/*
* FIXME: Check length.
*/
--- /dev/null
+TARGET = rlm_logintime.a
+SOURCES = rlm_logintime.c timestr.c
RLM_CFLAGS =
RLM_LDFLAGS =
RLM_LIBS =
-RLM_UTILS = smbencrypt
+RLM_UTILS = smbencrypt$(EXEEXT)
RLM_INSTALL =
# over-ride the previous assignment if we're not building anything
$(LT_OBJS): $(HEADERS)
-smbencrypt: smbencrypt.lo smbdes.lo $(LIBRADIUS)
+smbencrypt$(EXEEXT): smbencrypt.lo smbdes.lo $(LIBRADIUS)
@echo LINK $@ $^
@$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) \
-o $@ $^ $(RLM_LIBS) $(LIBS)
--- /dev/null
+SUBMAKEFILES := rlm_mschap.mk smbencrypt.mk
#include <ctype.h>
#include "smbdes.h"
+#include "mschap.h"
/*
* ntpwdhash converts Unicode password to 16-byte NT hash
--- /dev/null
+
+SOURCES := rlm_mschap.c smbdes.c opendir.c mschap.c
+
+TARGET := rlm_mschap.a
--- /dev/null
+TGT_PREREQS := libfreeradius-radius.a
+SOURCES := smbencrypt.c smbdes.c
+
+TGT_LDLIBS := $(LIBS)
+
+TARGET := smbencrypt
--- /dev/null
+# TARGET should be set by autoconf only. Don't touch it.
+# The SOURCES definition should list ALL source files.
+TARGET = rlm_otp.a
+SOURCES = otp_rlm.c otp_radstate.c otp_pwe.c otp_pw_valid.c
+SOURCES += otp_util.c otp_mppe.c
+SRC_CFLAGS = $(OPENSSL_INCLUDE)
+TGT_LDLIBS = $(OPENSSL_LIBS)
+
--- /dev/null
+TARGETNAME = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET = $(TARGETNAME).a
+endif
+
+SOURCES = rlm_pam.c
+
+SRC_CFLAGS = @pam_cflags@
+TGT_LDLIBS = @pam_ldflags@
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files Makefile"
+ ac_config_files="$ac_config_files Makefile all.mk"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
AC_SUBST(targetname)
AC_CONFIG_HEADER(config.h)
AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
--- /dev/null
+SOURCES := rlm_pap.c
+
+TARGET := rlm_pap.a
--- /dev/null
+TARGET = rlm_passwd.a
+SOURCES = rlm_passwd.c
int ignorenis;
char * filename;
struct mypasswd **table;
- struct mypasswd *last_found;
char buffer[1024];
FILE *fp;
char delimiter;
#undef passwd
}
-static struct mypasswd * get_next(char *name, struct hashtable *ht)
+static struct mypasswd * get_next(char *name, struct hashtable *ht,
+ struct mypasswd **last_found)
{
#define passwd ((struct mypasswd *) ht->buffer)
struct mypasswd * hashentry;
if (ht->tablesize > 0) {
/* get saved address of next item to check from buffer */
- hashentry = ht->last_found;
+ hashentry = *last_found;
for (; hashentry; hashentry = hashentry->next) {
if (!strcmp(hashentry->field[ht->keyfield], name)) {
/* save new address */
- ht->last_found = hashentry->next;
+ *last_found = hashentry->next;
return hashentry;
}
}
#undef passwd
}
-static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht)
+static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht,
+ struct mypasswd **last_found)
{
int h;
struct mypasswd * hashentry;
if (!ht || !name || *name == '\0') return NULL;
- ht->last_found = NULL;
+ *last_found = NULL;
if (ht->tablesize > 0) {
h = hash (name, ht->tablesize);
for (hashentry = ht->table[h]; hashentry; hashentry = hashentry->next)
if (!strcmp(hashentry->field[ht->keyfield], name)){
/* save address of next item to check into buffer */
- ht->last_found=hashentry->next;
+ *last_found=hashentry->next;
return hashentry;
}
return NULL;
ht->fp = NULL;
}
if (!(ht->fp=fopen(ht->filename, "r"))) return NULL;
- return get_next(name, ht);
+ return get_next(name, ht, last_found);
}
#ifdef TEST
int main(void){
struct hashtable *ht;
char *buffer;
- struct mypasswd* pw;
+ struct mypasswd* pw, *last_found;
int i;
ht = build_hash_table("/etc/group", 4, 3, 1, 100, 0, ":");
while(fgets(buffer, 1024, stdin)){
buffer[strlen(buffer)-1] = 0;
- pw = get_pw_nam(buffer, ht);
+ pw = get_pw_nam(buffer, ht, &last_found);
printpw(pw,4);
- while (pw = get_next(buffer, ht)) printpw(pw,4);
+ while (pw = get_next(buffer, ht, &last_found)) printpw(pw,4);
}
release_ht(ht);
}
return -1;
}
if(!inst->filename || *inst->filename == '\0' || !inst->format || *inst->format == '\0') {
- radlog(L_ERR, "rlm_passwd: cann't find passwd file and/or format in configuration");
+ radlog(L_ERR, "rlm_passwd: can't find passwd file and/or format in configuration");
+ free(inst);
return -1;
}
+
+ if (inst->hashsize == 0) {
+ radlog(L_ERR, "rlm_passwd: hashsize=0 is no longer permitted as it will break the server.");
+ free(inst);
+ return -1;
+ }
+
lf=strdup(inst->format);
if ( lf == NULL) {
radlog(L_ERR, "rlm_passwd: memory allocation failed for lf");
+ free(inst);
return -1;
}
memset(lf, 0, strlen(inst->format));
#define inst ((struct passwd_instance *)instance)
char buffer[1024];
VALUE_PAIR * key;
- struct mypasswd * pw;
+ struct mypasswd * pw, *last_found;
int found = 0;
for (key = request->packet->vps;
* Ensure we have the string form of the attribute
*/
vp_prints_value(buffer, sizeof(buffer), key, 0);
- if (! (pw = get_pw_nam(buffer, inst->ht)) ) {
+ if (! (pw = get_pw_nam(buffer, inst->ht, &last_found)) ) {
continue;
}
do {
addresult(inst, request, &request->config_items, pw, 0, "config_items");
addresult(inst, request, &request->reply->vps, pw, 1, "reply_items");
addresult(inst, request, &request->packet->vps, pw, 2, "request_items");
- } while ( (pw = get_next(buffer, inst->ht)) );
+ } while ( (pw = get_next(buffer, inst->ht, &last_found)) );
found++;
if (!inst->allowmultiple) break;
}
--- /dev/null
+TARGETNAME = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET = $(TARGETNAME).a
+endif
+
+SOURCES = rlm_perl.c
+
+SRC_CFLAGS = @perl_cflags@
+TGT_LDLIBS = @perl_ldflags@
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files Makefile"
+ ac_config_files="$ac_config_files Makefile all.mk"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
AC_SUBST(targetname)
AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
--- /dev/null
+TARGET = rlm_policy.a
+SOURCES = rlm_policy.c parse.c evaluate.c
/*
* Pop an item from the state.
*/
-static int policy_stack_pop(policy_state_t *state, const policy_item_t **pitem)
+static int policy_stack_pop(policy_state_t *state, const policy_item_t **item)
{
- rad_assert(pitem != NULL);
+ rad_assert(item != NULL);
rad_assert(state->depth >= 0);
redo:
if (state->depth == 0) {
- *pitem = NULL;
+ *item = NULL;
return 0;
}
- *pitem = state->stack[state->depth - 1];
+ *item = state->stack[state->depth - 1];
/*
* Named policies are on the stack for catching recursion.
*/
- if ((*pitem)->type == POLICY_TYPE_NAMED_POLICY) {
+ if ((*item)->type == POLICY_TYPE_NAMED_POLICY) {
state->depth--;
goto redo;
}
/*
* Process the whole item list.
*/
- if ((*pitem)->next) {
- state->stack[state->depth - 1] = (*pitem)->next;
- debug_evaluate("pop/push %d %p\n", state->depth - 1, *pitem);
+ if ((*item)->next) {
+ state->stack[state->depth - 1] = (*item)->next;
+ debug_evaluate("pop/push %d %p\n", state->depth - 1, *item);
} else {
state->depth--; /* points to unused entry */
- debug_evaluate("pop %d %p\n", state->depth, *pitem);
+ debug_evaluate("pop %d %p\n", state->depth, *item);
}
return 1;
}
if ((lexer->debug & POLICY_DEBUG_PRINT_POLICY) != 0) {
- rlm_policy_print(this);
+ rlm_policy_print((policy_item_t *) this);
}
return 1;
--- /dev/null
+TARGET = rlm_preprocess.a
+SOURCES = rlm_preprocess.c
int with_specialix_jetstream_hack;
int with_cisco_vsa_hack;
int with_alvarion_vsa_hack;
+ int with_cablelabs_vsa_hack;
} rlm_preprocess_t;
static const CONF_PARSER module_config[] = {
offsetof(rlm_preprocess_t,with_cisco_vsa_hack), NULL, "no" },
{ "with_alvarion_vsa_hack", PW_TYPE_BOOLEAN,
offsetof(rlm_preprocess_t,with_alvarion_vsa_hack), NULL, "no" },
+ { "with_cablelabs_vsa_hack", PW_TYPE_BOOLEAN,
+ offsetof(rlm_preprocess_t,with_cablelabs_vsa_hack), NULL, NULL },
{ NULL, -1, 0, NULL, NULL }
};
}
/*
+ * Cablelabs magic, taken from:
+ *
+ * http://www.cablelabs.com/packetcable/downloads/specs/PKT-SP-EM-I12-05812.pdf
+ *
+ * Sample data is:
+ *
+ * 0x0001d2d2026d30310000000000003030
+ * 3130303030000e812333000100033031
+ * 00000000000030303130303030000000
+ * 00063230313230313331303630323231
+ * 2e3633390000000081000500
+ */
+
+typedef struct cl_timezone_t {
+ uint8_t dst;
+ uint8_t sign;
+ uint8_t hh[2];
+ uint8_t mm[2];
+ uint8_t ss[2];
+} cl_timezone_t;
+
+typedef struct cl_bcid_t {
+ uint32_t timestamp;
+ uint8_t element_id[8];
+ cl_timezone_t timezone;
+ uint32_t event_counter;
+} cl_bcid_t;
+
+typedef struct cl_em_hdr_t {
+ uint16_t version;
+ cl_bcid_t bcid;
+ uint16_t message_type;
+ uint16_t element_type;
+ uint8_t element_id[8];
+ cl_timezone_t time_zone;
+ uint32_t sequence_number;
+ uint8_t event_time[18];
+ uint8_t status[4];
+ uint8_t priority;
+ uint16_t attr_count; /* of normal Cablelabs VSAs */
+ uint8_t event_object;
+} cl_em_hdr_t;
+
+
+static void cablelabs_vsa_hack(VALUE_PAIR **list)
+{
+ VALUE_PAIR *ev, *vp;
+
+ ev = pairfind(&list, 1, 4491); /* Cablelabs-Event-Message */
+ if (!ev) return;
+
+ /*
+ * FIXME: write 100's of lines of code to decode
+ * each data structure above.
+ */
+}
+
+
+
+/*
* Mangle username if needed, IN PLACE.
*/
static void rad_mangle(rlm_preprocess_t *data, REQUEST *request)
alvarion_vsa_hack(request->packet->vps);
}
+ if (data->with_cablelabs_vsa_hack) {
+ /*
+ * We need to run this hack because the Cablelabs
+ * people are crazy.
+ */
+ cablelabs_vsa_hack(&request->packet->vps);
+ }
+
/*
* Note that we add the Request-Src-IP-Address to the request
* structure BEFORE checking huntgroup access. This allows
alvarion_vsa_hack(request->packet->vps);
}
+ if (data->with_cablelabs_vsa_hack) {
+ /*
+ * We need to run this hack because the Cablelabs
+ * people are crazy.
+ */
+ cablelabs_vsa_hack(&request->packet->vps);
+ }
+
/*
* Ensure that we log the NAS IP Address in the packet.
*/
--- /dev/null
+TARGETNAME = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET = $(TARGETNAME).a
+endif
+
+SOURCES = rlm_python.c
+
+TGT_LDLIBS = @python_ldflags@
+SRC_CFLAGS = @python_cflags@
unset ac_cv_env_LIBS_set
unset ac_cv_env_LIBS_value
- ac_config_files="$ac_config_files Makefile"
+ ac_config_files="$ac_config_files Makefile all.mk"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
AC_SUBST(python_cflags)
AC_SUBST(targetname)
AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
--- /dev/null
+TARGET = rlm_radutmp.a
+SOURCES = rlm_radutmp.c
--- /dev/null
+TARGET := rlm_realm.a
+
+SOURCES := rlm_realm.c
TARGET = @targetname@
SRCS = rlm_rediswho.c
HEADERS = $(top_builddir)/src/modules/rlm_redis/rlm_redis.h
-RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_redis $(INCLTDL) @redis_cflags@
+RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_redis @redis_cflags@
RLM_LIBS = @redis_ldflags@
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_sim_files.a
+SOURCES = rlm_sim_files.c
SRCS = rlm_sql.c sql.c
HEADERS = rlm_sql.h conf.h
RLM_INSTALL = install-drivers
-RLM_CFLAGS = $(INCLTDL) -I$(top_builddir)/src/modules/rlm_sql
+RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_sql
RLM_LIBS = $(LIBLTDL)
RLM_SUBDIRS = drivers
--- /dev/null
+TARGET = rlm_sql.a
+SOURCES = rlm_sql.c sql.c
+# this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
TARGET = @targetname@
SRCS = sql_db2.c
-RLM_SQL_CFLAGS = @sql_ibmdb2_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_ibmdb2_cflags@
RLM_SQL_LIBS = @sql_ibmdb2_ldflags@
include ../rules.mak
TARGET = @targetname@
SRCS = sql_firebird.c sql_fbapi.c
HEADERS = sql_fbapi.h
-RLM_SQL_CFLAGS = @sql_firebird_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_firebird_cflags@
RLM_SQL_LIBS = @sql_firebird_ldflags@
# this uses the RLM_SQL_CFLAGS and RLM_SQL_LIBS and SRCS defs to make TARGET.
TARGET = @targetname@
SRCS = sql_iodbc.c
-RLM_SQL_CFLAGS = @sql_iodbc_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_iodbc_cflags@
RLM_SQL_LIBS = @sql_iodbc_ldflags@
include ../rules.mak
TARGET = @targetname@
SRCS = sql_mysql.c
-RLM_SQL_CFLAGS = @sql_mysql_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_mysql_cflags@
RLM_SQL_LIBS = @sql_mysql_ldflags@
include ../rules.mak
mysql_init(&(mysql_sock->conn));
mysql_options(&(mysql_sock->conn), MYSQL_READ_DEFAULT_GROUP, "freeradius");
+
+#if (MYSQL_VERSION_ID >= 50000)
+ if (config->query_timeout) {
+ unsigned int timeout = config->query_timeout;
+
+ /*
+ * 3 retries are hard-coded into the MySQL library.
+ * We ensure that the REAL timeout is what the user
+ * set by accounting for that.
+ */
+ if (timeout > 3) timeout /= 3;
+
+ mysql_options(&(mysql_sock->conn), MYSQL_OPT_CONNECT_TIMEOUT,
+ &timeout);
+ mysql_options(&(mysql_sock->conn), MYSQL_OPT_READ_TIMEOUT,
+ &timeout);
+ mysql_options(&(mysql_sock->conn), MYSQL_OPT_WRITE_TIMEOUT,
+ &timeout);
+ }
+#endif
+
#if (MYSQL_VERSION_ID >= 40100)
sql_flags = CLIENT_MULTI_RESULTS | CLIENT_FOUND_ROWS;
#else
TARGET = @targetname@
SRCS = sql_oracle.c
-RLM_SQL_CFLAGS = @sql_oracle_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_oracle_cflags@
RLM_SQL_LIBS = @sql_oracle_ldflags@
include ../rules.mak
TARGET = @targetname@
SRCS = sql_postgresql.c
-RLM_SQL_CFLAGS = @postgresql_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @postgresql_cflags@
RLM_SQL_LIBS = @postgresql_ldflags@
include ../rules.mak
TARGET = @targetname@
SRCS = sql_sqlite.c
-RLM_SQL_CFLAGS = @sql_sqlite_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_sqlite_cflags@
RLM_SQL_LIBS = @sql_sqlite_ldflags@
include ../rules.mak
TARGET =
#TARGET = rlm_sql_sybase
SRCS = sql_sybase.c
-RLM_SQL_CFLAGS = $(INCLTDL) -I/opt/sybase/OCS-12_0/include
+RLM_SQL_CFLAGS = -I/opt/sybase/OCS-12_0/include
RLM_SQL_LIBS = -L/opt/sybase/OCS-12_0/lib -ltcl -lcomn -lintl -lnsl -ldl -lm -lcs -lct
include ../rules.mak
TARGET = @targetname@
SRCS = sql_unixodbc.c
-RLM_SQL_CFLAGS = @sql_unixodbc_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_unixodbc_cflags@
RLM_SQL_LIBS = @sql_unixodbc_ldflags@
include ../rules.mak
--- /dev/null
+TARGET = rlm_sql_log.a
+SOURCES = rlm_sql_log.c
static size_t sql_utf8_escape_func(char *out, size_t outlen, const char *in)
{
- int len = 0;
- int utf8 = 0;
+ size_t len = 0;
+ size_t utf8 = 0;
while (in[0]) {
/*
* Skip over UTF8 characters
*/
- utf8 = fr_utf8_char((uint8_t *)in);
+ utf8 = fr_utf8_char((const uint8_t *)in);
if (utf8) {
if (outlen <= utf8) {
break;
--- /dev/null
+TARGET = rlm_sqlcounter.a
+SOURCES = rlm_sqlcounter.c
TARGET = @targetname@
SRCS = rlm_sqlhpwippool.c
HEADERS =
-RLM_CFLAGS = $(INCLTDL) @sqlhpwippool_cflags@ -I$(top_builddir)/src/modules/rlm_sql
+RLM_CFLAGS = @sqlhpwippool_cflags@ -I$(top_builddir)/src/modules/rlm_sql
RLM_LIBS = $(LIBLTDL) @sqlhpwippool_ldflags@
RLM_INSTALL =
TARGET = @targetname@
SRCS = rlm_sqlippool.c
HEADERS = $(top_builddir)/src/modules/rlm_sql/rlm_sql.h
-RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_sql $(INCLTDL)
+RLM_CFLAGS = -I$(top_builddir)/src/modules/rlm_sql
RLM_LIBS =
RLM_INSTALL =
--- /dev/null
+TARGET = rlm_sqlippool.a
+SOURCES = rlm_sqlippool.c
+
+SRC_INCDIRS := $(top_builddir)/src/modules/rlm_sql
--- /dev/null
+TARGET = rlm_unix.a
+SOURCES = rlm_unix.c
/*
* The Group = handler.
*/
-static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
+static int groupcmp(void *instance, REQUEST *req, UNUSED VALUE_PAIR *request,
VALUE_PAIR *check, VALUE_PAIR *check_pairs,
VALUE_PAIR **reply_pairs)
{
struct passwd *pwd;
struct group *grp;
char **member;
- char *username;
int retval;
- VALUE_PAIR *vp;
instance = instance;
check_pairs = check_pairs;
+++ /dev/null
-TARGET = rlm_wimax
-SRCS = rlm_wimax.c
-HEADERS =
-RLM_CFLAGS =
-RLM_LIBS = $(OPENSSL_LIBS)
-
-include ../rules.mak
-
-$(STATIC_OBJS): $(HEADERS)
-
-$(DYNAMIC_OBJS): $(HEADERS)
--- /dev/null
+TARGET = rlm_wimax.a
+SOURCES = rlm_wimax.c
WHERE=$(shell pwd)
build-module: $(TARGET).la $(RLM_UTILS)
- @[ "x$(RLM_SUBDIRS)" = "x" ] || $(MAKE) $(MFLAGS) WHAT_TO_MAKE=all common
@[ -d $(top_builddir)/src/modules/lib/.libs ] || mkdir $(top_builddir)/src/modules/lib/.libs
@for x in .libs/* $^; do \
rm -rf $(top_builddir)/src/modules/lib/$$x; \
ln -s $(WHERE)/$$x $(top_builddir)/src/modules/lib/$$x; \
done
-$(TARGET).la: $(LT_OBJS)
+$(TARGET).la: $(RLM_SUBDIRS) $(LT_OBJS)
@echo LINK $@ $^
@$(LIBTOOL) --quiet --mode=link $(CC) -release $(RADIUSD_VERSION) \
-module $(LINK_MODE) $(LDFLAGS) $(RLM_LDFLAGS) -o $@ \