home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / etc / wpa_supplicant / functions.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  2010-02-10  |  25.6 KB  |  1,013 lines

  1. #!/bin/sh
  2.  
  3. #####################################################################
  4. ## Purpose
  5. # This file contains common shell functions used by scripts of the
  6. # wpasupplicant package to allow ifupdown to manage wpa_supplicant.
  7. # It also contains some functions used by wpa_action(8) that allow
  8. # ifupdown to be managed by wpa_cli(8) action events.
  9. #
  10. # This file is provided by the wpasupplicant package.
  11.  
  12. #####################################################################
  13. # Copyright (C) 2006 - 2009 Debian/Ubuntu wpasupplicant Maintainers 
  14. # <pkg-wpa-devel@lists.alioth.debian.org>
  15. #
  16. # This program is free software; you can redistribute it and/or
  17. # modify it under the terms of the GNU General Public License
  18. # as published by the Free Software Foundation; either version 2
  19. # of the License, or (at your option) any later version.
  20. #
  21. # This program is distributed in the hope that it will be useful,
  22. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. # GNU General Public License for more details.
  25. #
  26. # On Debian GNU/Linux systems, the text of the GPL license,
  27. # version 2, can be found in /usr/share/common-licenses/GPL-2.
  28.  
  29. #####################################################################
  30. ## global variables
  31. # wpa_supplicant variables
  32. WPA_SUP_BIN="/sbin/wpa_supplicant"
  33. WPA_SUP_PNAME="wpa_supplicant"
  34. WPA_SUP_PIDFILE="/var/run/wpa_supplicant.${WPA_IFACE}.pid"
  35.  
  36. # wpa_cli variables
  37. WPA_CLI_BIN="/sbin/wpa_cli"
  38. WPA_CLI_PNAME="wpa_cli"
  39. WPA_CLI_PIDFILE="/var/run/wpa_action.${WPA_IFACE}.pid"
  40. WPA_CLI_TIMESTAMP="/var/run/wpa_action.${WPA_IFACE}.timestamp"
  41. WPA_CLI_IFUPDOWN="/var/run/wpa_action.${WPA_IFACE}.ifupdown"
  42.  
  43. # sendsigs omission interface, present in initscripts (>= 2.86.ds1-48)
  44. if [ -d /lib/init/rw/sendsigs.omit.d/ ]; then
  45.     # Debian
  46.     WPA_SUP_OMIT_PIDFILE="/lib/init/rw/sendsigs.omit.d/wpasupplicant.wpa_supplicant.${WPA_IFACE}.pid"
  47. elif [ -d /var/run/sendsigs.omit.d/ ]; then
  48.     # Ubuntu, see https://launchpad.net/bugs/181541 for status
  49.     WPA_SUP_OMIT_PIDFILE="/var/run/sendsigs.omit.d/wpasupplicant.wpa_supplicant.${WPA_IFACE}.pid"
  50. else
  51.     WPA_SUP_OMIT_PIDFILE=
  52. fi
  53.  
  54. # default ctrl_interface socket directory
  55. if [ -z "$WPA_CTRL_DIR" ]; then
  56.     WPA_CTRL_DIR="/var/run/wpa_supplicant"
  57. fi
  58.  
  59. # verbosity variables
  60. if [ -n "$IF_WPA_VERBOSITY" ] || [ "$VERBOSITY" = "1" ]; then
  61.     TO_NULL="/dev/stdout"
  62.     DAEMON_VERBOSITY="--verbose"
  63. else
  64.     TO_NULL="/dev/null"
  65.     DAEMON_VERBOSITY="--quiet"
  66. fi
  67.  
  68. #####################################################################
  69. ## wpa_cli wrapper
  70. # Path to common ctrl_interface socket and iface supplied.
  71. # NB: WPA_CTRL_DIR cannot be used for interactive commands, it is
  72. # set only in the environment that wpa_cli provides when processing
  73. # action events.
  74. #
  75. wpa_cli () {
  76.     "$WPA_CLI_BIN" -p "$WPA_CTRL_DIR" -i "$WPA_IFACE" "$@"
  77.  
  78.     return "$?"
  79. }
  80.  
  81. #####################################################################
  82. ## verbose and stderr message wrapper
  83. # Ensures a standard and easily identifiable message is printed by
  84. # scripts using this function library.
  85. #
  86. # log        Log a message to syslog when called non-interactively
  87. #        by wpa_action
  88. #
  89. # verbose    To stdout when IF_WPA_VERBOSITY or VERBOSITY is true
  90. #
  91. # action    Same as verbose but without newline
  92. #        Useful for allowing wpa_cli commands to echo result
  93. #        value of 'OK' or 'FAILED'
  94. #
  95. # stderr    Echo warning or error messages to stderr
  96. #
  97. # NB: when called by wpa_action, there is no redirection (verbose)
  98. #
  99. wpa_msg () {
  100.     if [ "$1" = "log" ]; then
  101.         shift
  102.         case "$WPA_ACTION" in
  103.             "CONNECTED"|"DISCONNECTED")
  104.                 [ -x /usr/bin/logger ] || return
  105.                 if [ "$#" -gt 0 ]; then
  106.                     logger -t "wpa_action" "$@"
  107.                 else
  108.                     logger -t "wpa_action"
  109.                 fi
  110.                 ;;
  111.             *)
  112.                 [ "$#" -gt 0 ] && echo "wpa_action: $@"
  113.                 ;;
  114.         esac
  115.         return
  116.     fi
  117.     
  118.     case "$1" in 
  119.         "verbose")
  120.             shift
  121.             echo "$WPA_SUP_PNAME: $@" >$TO_NULL
  122.             ;;
  123.         "action")
  124.             shift
  125.             echo -n "$WPA_SUP_PNAME: $@ -- " >$TO_NULL
  126.             ;;
  127.         "stderr")
  128.             shift
  129.             echo "$WPA_SUP_PNAME: $@" >/dev/stderr
  130.             ;;
  131.         *)
  132.             ;;
  133.     esac
  134. }
  135.  
  136. #####################################################################
  137. ## validate daemon pid files
  138. # Test daemon process ID files via start-stop-daemon with a signal 0
  139. # given the exec binary and pidfile location.
  140. #
  141. # $1    daemon
  142. # $2    pidfile
  143. #
  144. # Returns true when pidfile exists, the process ID exists _and_ was
  145. # created by the exec binary.
  146. #
  147. # If the test fails, but the pidfile exists, it is stale
  148. #
  149. test_daemon_pidfile () {
  150.     local DAEMON
  151.     local PIDFILE
  152.     
  153.     if [ -n "$1" ]; then
  154.         DAEMON="$1"
  155.     fi
  156.     
  157.     if [ -f "$2" ]; then
  158.         PIDFILE="$2"
  159.     fi
  160.     
  161.     if [ -n "$DAEMON" ] && [ -f "$PIDFILE" ]; then
  162.         if start-stop-daemon --stop --quiet --signal 0 \
  163.             --exec "$DAEMON" --pidfile "$PIDFILE"; then
  164.             return 0
  165.         else
  166.             rm -f "$PIDFILE"
  167.             return 1
  168.         fi
  169.     else
  170.         return 1
  171.     fi
  172. }
  173.  
  174. # validate wpa_supplicant pidfile
  175. test_wpa_supplicant () {
  176.     test_daemon_pidfile "$WPA_SUP_BIN" "$WPA_SUP_PIDFILE"
  177. }
  178.  
  179. # validate wpa_cli pidfile
  180. test_wpa_cli () {
  181.     test_daemon_pidfile "$WPA_CLI_BIN" "$WPA_CLI_PIDFILE"
  182. }
  183.  
  184. #####################################################################
  185. ## daemonize wpa_supplicant
  186. # Start wpa_supplicant via start-stop-dameon with all required
  187. # options. Will start if environment variable WPA_SUP_CONF is present
  188. #
  189. # Default options:
  190. # -B    dameonize/background process
  191. # -D    driver backend ('wext' if none given)
  192. # -P    process ID file
  193. # -C    path to ctrl_interface socket directory
  194. # -s    log to syslog
  195. #
  196. # Conditional options:
  197. # -c    configuration file
  198. # -W    wait for wpa_cli to attach to ctrl_interface socket
  199. # -b    bridge interface name
  200. # -f    path to log file
  201. #
  202. init_wpa_supplicant () {
  203.     [ -n "$WPA_SUP_CONF" ] || return 0
  204.  
  205.     local WPA_SUP_OPTIONS
  206.     WPA_SUP_OPTIONS="-s -B -P $WPA_SUP_PIDFILE -i $WPA_IFACE"
  207.  
  208.     if [ -n "$WPA_ACTION_SCRIPT" ]; then
  209.         if [ -x "$WPA_ACTION_SCRIPT" ]; then
  210.             WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -W"
  211.             wpa_msg verbose "wait for wpa_cli to attach"
  212.         else
  213.             wpa_msg stderr "action script \"$WPA_ACTION_SCRIPT\" not executable"
  214.             return 1
  215.         fi
  216.     fi
  217.  
  218.     if [ -n "$IF_WPA_BRIDGE" ]; then
  219.         WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -b $IF_WPA_BRIDGE"
  220.         wpa_msg verbose "wpa-bridge $IF_WPA_BRIDGE"
  221.     fi
  222.  
  223.     if [ -n "$IF_WPA_DRIVER" ]; then
  224.         wpa_msg verbose "wpa-driver $IF_WPA_DRIVER"
  225.         case "$IF_WPA_DRIVER" in
  226.             hostap|ipw|madwifi|ndiswrapper)
  227.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D wext"
  228.                 wpa_msg stderr "\"$IF_WPA_DRIVER\" wpa-driver is unsupported"
  229.                 wpa_msg stderr "using \"wext\" wpa-driver instead ..."
  230.                 ;;
  231.             *)
  232.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D $IF_WPA_DRIVER"
  233.                 ;;
  234.         esac
  235.     else
  236.         WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D wext"
  237.         wpa_msg verbose "using default driver type: wpa-driver wext"
  238.     fi
  239.  
  240.     if [ -n "$IF_WPA_DEBUG_LEVEL" ]; then
  241.         case "$IF_WPA_DEBUG_LEVEL" in
  242.             3)
  243.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -ddd"
  244.                 ;;
  245.             2)
  246.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -dd"
  247.                 ;;
  248.             1)
  249.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -d"
  250.                 ;;
  251.             0)
  252.                 # wpa_supplicant default verbosity
  253.                 ;;
  254.             -1)
  255.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -q"
  256.                 ;;
  257.             -2)
  258.                 WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -qq"
  259.                 ;;
  260.         esac
  261.         wpa_msg verbose "using debug level: $IF_WPA_DEBUG_LEVEL"
  262.     fi
  263.  
  264.     if [ -n "$IF_WPA_LOGFILE" ]; then
  265.         # custom log file
  266.         WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -f $IF_WPA_LOGFILE"
  267.         WPA_SUP_LOGFILE="$IF_WPA_LOGFILE"
  268.         wpa_msg verbose "logging to $IF_WPA_LOGFILE"
  269.     fi
  270.  
  271.     wpa_msg verbose "$WPA_SUP_BIN $WPA_SUP_OPTIONS $WPA_SUP_CONF"
  272.         
  273.     start-stop-daemon --start --oknodo $DAEMON_VERBOSITY \
  274.         --name $WPA_SUP_PNAME --startas $WPA_SUP_BIN --pidfile $WPA_SUP_PIDFILE \
  275.         -- $WPA_SUP_OPTIONS $WPA_SUP_CONF
  276.  
  277.     if [ "$?" -ne 0 ]; then
  278.         wpa_msg stderr "$WPA_SUP_BIN daemon failed to start"
  279.         return 1
  280.     fi
  281.  
  282.     if [ -n "$WPA_SUP_OMIT_PIDFILE" ]; then
  283.         local WPA_PIDFILE_WAIT
  284.         local MAX_WPA_PIDFILE_WAIT
  285.         WPA_PIDFILE_WAIT="0"
  286.         MAX_WPA_PIDFILE_WAIT="5"
  287.         until [ -s "$WPA_SUP_PIDFILE" ]; do
  288.             if [ "$WPA_PIDFILE_WAIT" -ge "$MAX_WPA_PIDFILE_WAIT" ]; then
  289.                 wpa_msg stderr "timed out waiting for creation of $WPA_SUP_PIDFILE"
  290.                 return 1
  291.             else
  292.                 wpa_msg verbose "waiting for \"$WPA_SUP_PIDFILE\": " \
  293.                     "$WPA_PIDFILE_WAIT (max. $MAX_WPA_PIDFILE_WAIT)"
  294.             fi
  295.  
  296.             WPA_PIDFILE_WAIT=$(($WPA_PIDFILE_WAIT + 1))
  297.             sleep 1
  298.         done
  299.         wpa_msg verbose "creating sendsigs omission pidfile: $WPA_SUP_OMIT_PIDFILE"
  300.         cat "$WPA_SUP_PIDFILE" > "$WPA_SUP_OMIT_PIDFILE"
  301.     else
  302.         wpa_msg verbose "sendsigs omission pidfile not created"
  303.     fi
  304.  
  305.     local WPA_SOCKET_WAIT
  306.     local MAX_WPA_SOCKET_WAIT
  307.     WPA_SOCKET_WAIT="0"
  308.     MAX_WPA_SOCKET_WAIT="5"
  309.     until [ -S "$WPA_CTRL_DIR/$WPA_IFACE" ]; do
  310.         if [ "$WPA_SOCKET_WAIT" -ge "$MAX_WPA_SOCKET_WAIT" ]; then
  311.             wpa_msg stderr "ctrl_interface socket not found at $WPA_CTRL_DIR/$WPA_IFACE"
  312.             return 1
  313.         else
  314.             wpa_msg verbose "waiting for \"$WPA_CTRL_DIR/$WPA_IFACE\": " \
  315.                 "$WPA_SOCKET_WAIT (max. $MAX_WPA_SOCKET_WAIT)"
  316.         fi
  317.         
  318.         WPA_SOCKET_WAIT=$(($WPA_SOCKET_WAIT + 1))
  319.         sleep 1
  320.     done
  321.     
  322.     wpa_msg verbose "ctrl_interface socket located at $WPA_CTRL_DIR/$WPA_IFACE"
  323. }
  324.  
  325. #####################################################################
  326. ## stop wpa_supplicant process
  327. # Kill wpa_supplicant via start-stop-daemon, given the location of
  328. # the pidfile or ctrl_interface socket path and interface name
  329. #
  330. kill_wpa_supplicant () {
  331.     test_wpa_supplicant || return 0
  332.  
  333.     wpa_msg verbose "terminating $WPA_SUP_PNAME daemon via pidfile $WPA_SUP_PIDFILE"
  334.  
  335.     start-stop-daemon --stop --oknodo $DAEMON_VERBOSITY \
  336.         --exec $WPA_SUP_BIN --pidfile $WPA_SUP_PIDFILE
  337.  
  338.     if [ -f "$WPA_SUP_PIDFILE" ]; then
  339.         rm -f "$WPA_SUP_PIDFILE"
  340.     fi
  341.  
  342.     if [ -f "$WPA_SUP_OMIT_PIDFILE" ]; then
  343.         wpa_msg verbose "removing $WPA_SUP_OMIT_PIDFILE"
  344.         rm -f "$WPA_SUP_OMIT_PIDFILE"
  345.     fi
  346. }
  347.  
  348. #####################################################################
  349. ## reload wpa_supplicant process
  350. # Sending a HUP signal causes wpa_supplicant to reparse its
  351. # configuration file
  352. #
  353. reload_wpa_supplicant () {
  354.     if test_wpa_supplicant; then
  355.         wpa_msg verbose "reloading wpa_supplicant configuration file via HUP signal"
  356.         start-stop-daemon --stop --signal HUP \
  357.             --name "$WPA_SUP_PNAME" --pidfile "$WPA_SUP_PIDFILE"
  358.     else
  359.         wpa_msg verbose "cannot $WPA_ACTION, $WPA_SUP_PIDFILE does not exist"
  360.     fi
  361. }
  362.  
  363. #####################################################################
  364. ## daemonize wpa_cli and action script
  365. # If environment variable WPA_ACTION_SCRIPT is present, wpa_cli will
  366. # be spawned via start-stop-daemon
  367. #
  368. # Required options:
  369. # -a    action script => wpa_action
  370. # -P    process ID file
  371. # -B    background process
  372. #
  373. init_wpa_cli () {
  374.     [ -n "$WPA_ACTION_SCRIPT" ] || return 0
  375.  
  376.     local WPA_CLI_OPTIONS
  377.     WPA_CLI_OPTIONS="-B -P $WPA_CLI_PIDFILE -i $WPA_IFACE"
  378.  
  379.     wpa_msg verbose "$WPA_CLI_BIN $WPA_CLI_OPTIONS -p $WPA_CTRL_DIR -a $WPA_ACTION_SCRIPT"
  380.         
  381.     start-stop-daemon --start --oknodo $DAEMON_VERBOSITY \
  382.         --name $WPA_CLI_PNAME --startas $WPA_CLI_BIN --pidfile $WPA_CLI_PIDFILE \
  383.         -- $WPA_CLI_OPTIONS -p $WPA_CTRL_DIR -a $WPA_ACTION_SCRIPT
  384.  
  385.     if [ "$?" -ne 0 ]; then
  386.         wpa_msg stderr "$WPA_CLI_BIN daemon failed to start"
  387.         return 1
  388.     fi
  389. }
  390.  
  391. #####################################################################
  392. ## stop wpa_cli process
  393. # Kill wpa_cli via start-stop-daemon, given the location of the
  394. # pidfile
  395. #
  396. kill_wpa_cli () {
  397.     test_wpa_cli || return 0
  398.     
  399.     wpa_msg verbose "terminating $WPA_CLI_PNAME daemon via pidfile $WPA_CLI_PIDFILE"
  400.     
  401.     start-stop-daemon --stop --oknodo $DAEMON_VERBOSITY \
  402.         --exec $WPA_CLI_BIN --pidfile $WPA_CLI_PIDFILE
  403.     
  404.     if [ -f "$WPA_CLI_PIDFILE" ]; then
  405.         rm -f "$WPA_CLI_PIDFILE"
  406.     fi
  407.  
  408.     if [ -f "$WPA_CLI_TIMESTAMP" ]; then
  409.         rm -f "$WPA_CLI_TIMESTAMP"
  410.     fi
  411.  
  412.     if [ -L "$WPA_CLI_IFUPDOWN" ]; then
  413.         rm -f "$WPA_CLI_IFUPDOWN"
  414.     fi
  415. }
  416.  
  417. #####################################################################
  418. ## higher level wpa_cli wrapper for variable and set_network commands
  419. # wpa_cli_do <value> <type> <variable> [set_network variable] <desc>
  420. #
  421. # $1    envorinment variable
  422. # $2    data type of variable {raw|ascii}
  423. # $3    wpa_cli variable, if $3 is set_network, shift and take 
  424. #    set_network subvariable
  425. # $4    wpa-* string as it would appear in interfaces file, enhances
  426. #    verbose messages
  427. #
  428. wpa_cli_do () {
  429.     if [ -z "$1" ]; then
  430.         return 0
  431.     fi
  432.     
  433.     local WPACLISET_VALUE
  434.     local WPACLISET_VARIABLE
  435.     local WPACLISET_DESC
  436.     
  437.     case "$2" in
  438.         ascii)
  439.             # Double quote
  440.             WPACLISET_VALUE="\"$1\""
  441.             ;;
  442.         raw|*)
  443.             # Provide raw value
  444.             WPACLISET_VALUE="$1"
  445.             ;;
  446.     esac
  447.     
  448.     case "$3" in
  449.         set_network)
  450.             if [ -z "$WPA_ID" ]; then
  451.                 return 1
  452.             fi
  453.             shift
  454.             WPACLISET_VARIABLE="set_network $WPA_ID $3"
  455.             ;;
  456.         *)
  457.             WPACLISET_VARIABLE="$3"
  458.             ;;
  459.     esac
  460.     
  461.     case "$4" in
  462.         *-psk|*-passphrase|*-passwd*|*-wep-key*)
  463.             WPACLISET_DESC="$4 *****"
  464.             ;;
  465.         *)
  466.             WPACLISET_DESC="$4 $WPACLISET_VALUE"
  467.             ;;
  468.     esac
  469.  
  470.     wpa_msg action "$WPACLISET_DESC"
  471.     
  472.     wpa_cli $WPACLISET_VARIABLE "$WPACLISET_VALUE" >$TO_NULL
  473.  
  474.     if [ "$?" -ne 0 ]; then
  475.         wpa_msg stderr "$WPACLISET_DESC failed!"
  476.     fi
  477. }
  478.  
  479. #####################################################################
  480. ## check value data type in plaintext or hex
  481. # returns 0 if input consists of hexadecimal digits only, 1 otherwise
  482. #
  483. ishex () {
  484.     if [ -z "$1" ]; then 
  485.         return 0
  486.     fi
  487.     
  488.     case "$1" in
  489.         *[!0-9a-fA-F]*)
  490.             # plaintext
  491.             return 1
  492.             ;;
  493.         *)
  494.             # hexadecimal
  495.             return 0
  496.             ;;
  497.     esac
  498. }
  499.  
  500. #####################################################################
  501. ## sanity check and set psk|passphrase
  502. # Warn about strange psk|passphrase values
  503. #
  504. # $1    psk or passphrase value
  505. # If psk is surrounded by quotes strip them.
  506. #
  507. # If psk contains all hexadecimal characters and string length is 64:
  508. #    is 256bit hexadecimal
  509. # else:
  510. #     is plaintext
  511. #
  512. # plaintext passphrases must be 8 - 63 characters in length
  513. # 256-bit hexadecimal key must be 64 characters in length
  514. #
  515. wpa_key_check_and_set () {
  516.     if [ "$#" -ne 3 ]; then
  517.         return 0
  518.     fi
  519.  
  520.     local KEY
  521.     local KEY_LEN
  522.     local KEY_TYPE
  523.     local ENC_TYPE
  524.     
  525.     case "$1" in
  526.         '"'*'"')
  527.             # Strip surrounding quotation marks
  528.             KEY=$(echo -n "$1" | sed 's/^"//;s/"$//')
  529.             ;;
  530.         *)
  531.             KEY="$1"
  532.             ;;
  533.     esac
  534.  
  535.     KEY_LEN="${#KEY}"
  536.  
  537.     case "$2" in
  538.         wep_key*)
  539.             ENC_TYPE="WEP"
  540.             ;;
  541.         psk)
  542.             ENC_TYPE="WPA"
  543.             ;;
  544.         *)
  545.             return 0
  546.             ;;
  547.     esac
  548.  
  549.     if [ "$ENC_TYPE" = "WEP" ]; then
  550.         if ishex "$KEY"; then
  551.             case "$KEY_LEN" in
  552.                 10|26|32|58)
  553.                     # 64/128/152/256-bit WEP
  554.                     KEY_TYPE="raw"
  555.                     ;;
  556.                 *)
  557.                     KEY_TYPE="ascii"
  558.                     ;;
  559.             esac
  560.         else
  561.             KEY_TYPE="ascii"
  562.         fi
  563.  
  564.         if [ "$KEY_TYPE" = "ascii" ]; then
  565.             if [ "$KEY_LEN" -lt "5" ]; then
  566.                 wpa_msg stderr "WARNING: plaintext or ascii WEP key has $KEY_LEN characters,"
  567.                 wpa_msg stderr "it must have at least 5 to be valid."
  568.             fi
  569.         fi
  570.     elif [ "$ENC_TYPE" = "WPA" ]; then
  571.         if ishex "$KEY"; then
  572.             case "$KEY_LEN" in
  573.                 64)
  574.                     # 256-bit WPA
  575.                     KEY_TYPE="raw"
  576.                     ;;
  577.                 *)
  578.                     KEY_TYPE="ascii"
  579.                     ;;
  580.             esac
  581.         else
  582.             KEY_TYPE="ascii"
  583.         fi
  584.  
  585.         if [ "$KEY_TYPE" = "ascii" ]; then
  586.             if [ "$KEY_LEN" -lt "8" ] || [ "$KEY_LEN" -gt "63" ]; then
  587.                 wpa_msg stderr "WARNING: plaintext or ascii WPA key has $KEY_LEN characters,"
  588.                 wpa_msg stderr "it must have between 8 and 63 to be valid."
  589.                 wpa_msg stderr "If the WPA key is a 256-bit hexadecimal key, it must have"
  590.                 wpa_msg stderr "exactly 64 characters."
  591.             fi
  592.         fi
  593.     fi
  594.  
  595.     wpa_cli_do "$KEY" "$KEY_TYPE" set_network "$2" "$3"
  596. }
  597.  
  598. #####################################################################
  599. ## formulate a usable configuration from interfaces(5) wpa- lines
  600. # A series of wpa_cli commands corresponding to environment variables
  601. # created as a result of wpa- lines in an interfaces stanza.
  602. #
  603. # NB: no-act when roaming daemon is used (to avoid prematurely
  604. # attaching to ctrl_interface socket)
  605. #
  606. conf_wpa_supplicant () {
  607.     if [ -n "$WPA_ACTION_SCRIPT" ]; then
  608.         return 0
  609.     fi
  610.  
  611.     if [ "$IF_WPA_DRIVER" = "wired" ]; then
  612.         IF_WPA_AP_SCAN="0"
  613.         wpa_msg verbose "forcing ap_scan=0 (required for wired IEEE8021X auth)"
  614.     fi
  615.  
  616.     if [ -n "$IF_WPA_ESSID" ]; then
  617.         # #403316, be similar to wireless tools
  618.         IF_WPA_SSID="$IF_WPA_ESSID"
  619.     fi
  620.     
  621.     wpa_cli_do "$IF_WPA_AP_SCAN" raw \
  622.         ap_scan wpa-ap-scan
  623.     
  624.     wpa_cli_do "$IF_WPA_PREAUTHENTICATE" raw \
  625.         preauthenticate wpa-preauthenticate
  626.         
  627.     if [ -n "$IF_WPA_SSID" ] || [ "$IF_WPA_DRIVER" = "wired" ] || \
  628.         [ -n "$IF_WPA_KEY_MGMT" ]; then
  629.         
  630.         case "$IF_WPA_SSID" in
  631.             '"'*'"')
  632.                 IF_WPA_SSID=$(echo -n "$IF_WPA_SSID" | sed 's/^"//;s/"$//')
  633.                 ;;
  634.             *)
  635.                 ;;
  636.         esac
  637.         
  638.         WPA_ID=$(wpa_cli add_network)
  639.  
  640.         wpa_msg verbose "configuring network block -- $WPA_ID"
  641.         
  642.         wpa_cli_do "$IF_WPA_SSID" ascii \
  643.             set_network ssid wpa-ssid
  644.         
  645.         wpa_cli_do "$IF_WPA_PRIORITY" raw \
  646.             set_network priority wpa-priority
  647.         
  648.         wpa_cli_do "$IF_WPA_BSSID" raw \
  649.             set_network bssid wpa-bssid
  650.         
  651.         if [ -s "$IF_WPA_PSK_FILE" ]; then
  652.             IF_WPA_PSK=$(cat "$IF_WPA_PSK_FILE")
  653.         fi
  654.         
  655.         # remain compat with wpa-passphrase-file
  656.         if [ -s "$IF_WPA_PASSPHRASE_FILE" ]; then
  657.             IF_WPA_PSK=$(cat "$IF_WPA_PASSPHRASE_FILE")
  658.         fi
  659.         
  660.         # remain compat with wpa-passphrase
  661.         if [ -n "$IF_WPA_PASSPHRASE" ]; then
  662.             IF_WPA_PSK="$IF_WPA_PASSPHRASE"
  663.         fi
  664.     
  665.         if [ -n "$IF_WPA_PSK" ]; then
  666.             wpa_key_check_and_set "$IF_WPA_PSK" \
  667.                 psk wpa-psk
  668.         fi
  669.         
  670.         wpa_cli_do "$IF_WPA_PAIRWISE" raw \
  671.             set_network pairwise wpa-pairwise
  672.         
  673.         wpa_cli_do "$IF_WPA_GROUP" raw \
  674.             set_network group wpa-group
  675.  
  676.         wpa_cli_do "$IF_WPA_MODE" raw \
  677.             set_network mode wpa-mode
  678.  
  679.         wpa_cli_do "$IF_WPA_FREQUENCY" raw \
  680.             set_network frequency wpa-frequency
  681.         
  682.         wpa_cli_do "$IF_WPA_KEY_MGMT" raw \
  683.             set_network key_mgmt wpa-key-mgmt
  684.         
  685.         wpa_cli_do "$IF_WPA_PROTO" raw \
  686.             set_network proto wpa-proto
  687.         
  688.         wpa_cli_do "$IF_WPA_AUTH_ALG" raw \
  689.             set_network auth_alg wpa-auth-alg
  690.         
  691.         wpa_cli_do "$IF_WPA_SCAN_SSID" raw \
  692.             set_network scan_ssid wpa-scan-ssid
  693.         
  694.         wpa_cli_do "$IF_WPA_IDENTITY" ascii \
  695.             set_network identity wpa-identity
  696.         
  697.         wpa_cli_do "$IF_WPA_ANONYMOUS_IDENTITY" ascii \
  698.             set_network anonymous_identity wpa-anonymous-identity
  699.         
  700.         wpa_cli_do "$IF_WPA_EAP" raw \
  701.             set_network eap wpa-eap
  702.         
  703.         wpa_cli_do "$IF_WPA_EAPPSK" raw \
  704.             set_network eappsk wpa-eappsk
  705.  
  706.         wpa_cli_do "$IF_WPA_NAI" ascii \
  707.             set_network nai wpa-nai
  708.  
  709.         wpa_cli_do "$IF_WPA_PASSWORD" ascii \
  710.             set_network password wpa-password
  711.  
  712.         wpa_cli_do "$IF_WPA_CA_CERT" ascii \
  713.             set_network ca_cert wpa-ca-cert
  714.  
  715.         wpa_cli_do "$IF_WPA_CA_PATH" ascii \
  716.             set_network ca_path wpa-ca-path
  717.  
  718.         wpa_cli_do "$IF_WPA_CLIENT_CERT" ascii \
  719.             set_network client_cert wpa-client-cert
  720.  
  721.         wpa_cli_do "$IF_WPA_PRIVATE_KEY" ascii \
  722.             set_network private_key wpa-private-key
  723.  
  724.         wpa_cli_do "$IF_WPA_PRIVATE_KEY_PASSWD" ascii \
  725.             set_network private_key_passwd wpa-private-key-passwd
  726.         
  727.         wpa_cli_do "$IF_WPA_DH_FILE" ascii \
  728.             set_network dh_file wpa-dh-file
  729.  
  730.         wpa_cli_do "$IF_WPA_SUBJECT_MATCH" ascii \
  731.             set_network subject_match wpa-subject-match
  732.  
  733.         wpa_cli_do "$IF_WPA_ALTSUBJECT_MATCH" ascii \
  734.             set_network altsubject_match wpa-altsubject-match
  735.  
  736.         wpa_cli_do "$IF_WPA_CA_CERT2" ascii \
  737.             set_network ca_cert2 wpa-ca-cert2
  738.  
  739.         wpa_cli_do "$IF_WPA_CA_PATH2" ascii \
  740.             set_network ca_path2 wpa-ca-path2
  741.  
  742.         wpa_cli_do "$IF_WPA_CLIENT_CERT2" ascii \
  743.             set_network client_cert2 wpa-client-cert2
  744.  
  745.         wpa_cli_do "$IF_WPA_PRIVATE_KEY2" ascii \
  746.             set_network private_key2 wpa-private-key2
  747.  
  748.         wpa_cli_do "$IF_WPA_PRIVATE_KEY_PASSWD2" ascii \
  749.             set_network private_key_passwd2 wpa-private-key-passwd2
  750.         
  751.         wpa_cli_do "$IF_WPA_DH_FILE2" ascii \
  752.             set_network dh_file2 wpa-dh-file2
  753.  
  754.         wpa_cli_do "$IF_WPA_SUBJECT_MATCH2" ascii \
  755.             set_network subject_match2 wpa-subject-match2
  756.  
  757.         wpa_cli_do "$IF_WPA_ALTSUBJECT_MATCH2" ascii \
  758.             set_network altsubject_match2 wpa-altsubject-match2
  759.         
  760.         wpa_cli_do "$IF_WPA_EAP_METHODS" raw \
  761.             set_network eap_methods wpa-eap-methods
  762.  
  763.         wpa_cli_do "$IF_WPA_PHASE1" ascii \
  764.             set_network phase1 wpa-phase1
  765.  
  766.         wpa_cli_do "$IF_WPA_PHASE2" ascii \
  767.             set_network phase2 wpa-phase2
  768.  
  769.         wpa_cli_do "$IF_WPA_PCSC" raw \
  770.             set_network pcsc wpa-pcsc
  771.  
  772.         wpa_cli_do "$IF_WPA_PIN" ascii \
  773.             set_network pin wpa-pin
  774.  
  775.         wpa_cli_do "$IF_WPA_ENGINE" raw \
  776.             set_network engine wpa-engine
  777.  
  778.         wpa_cli_do "$IF_WPA_ENGINE_ID" ascii \
  779.             set_network engine_id wpa-engine-id
  780.  
  781.         wpa_cli_do "$IF_WPA_KEY_ID" ascii \
  782.             set_network key_id wpa-key-id
  783.  
  784.         wpa_cli_do "$IF_WPA_EAPOL_FLAGS" raw \
  785.             set_network eapol_flags wpa-eapol-flags
  786.         
  787.         if [ -n "$IF_WPA_WEP_KEY0" ]; then
  788.             wpa_key_check_and_set "$IF_WPA_WEP_KEY0" \
  789.                 wep_key0 wpa-wep-key0
  790.         fi
  791.         
  792.         if [ -n "$IF_WPA_WEP_KEY1" ]; then
  793.             wpa_key_check_and_set "$IF_WPA_WEP_KEY1" \
  794.                 wep_key1 wpa-wep-key1
  795.         fi
  796.  
  797.         if [ -n "$IF_WPA_WEP_KEY2" ]; then
  798.             wpa_key_check_and_set "$IF_WPA_WEP_KEY2" \
  799.                 wep_key2 wpa-wep-key2
  800.         fi
  801.  
  802.         if [ -n "$IF_WPA_WEP_KEY3" ]; then
  803.             wpa_key_check_and_set "$IF_WPA_WEP_KEY3" \
  804.                 wep_key3 wpa-wep-key3
  805.         fi
  806.         
  807.         wpa_cli_do "$IF_WPA_WEP_TX_KEYIDX" raw \
  808.             set_network wep_tx_keyidx wpa-wep-tx-keyidx
  809.         
  810.         wpa_cli_do "$IF_WPA_PROACTIVE_KEY_CACHING" raw \
  811.             set_network proactive_key_caching wpa-proactive-key-caching
  812.             
  813.         wpa_cli_do "$IF_WPA_PAC_FILE" ascii \
  814.             set_network pac_file wpa-pac-file
  815.         
  816.         wpa_cli_do "$IF_WPA_MODE" raw \
  817.             set_network mode wpa-mode
  818.         
  819.         wpa_cli_do "$IF_WPA_PEERKEY" raw \
  820.             set_network peerkey wpa-peerkey
  821.             
  822.         wpa_cli_do "$IF_FRAGMENT_SIZE" raw \
  823.             set_network fragment_size wpa-fragment-size
  824.  
  825.         wpa_cli_do "$IF_WPA_ID_STR" ascii \
  826.             set_network id_str wpa-id-str
  827.         
  828.         wpa_cli_do "$WPA_ID" raw \
  829.             enable_network "enabling network block"
  830.     fi
  831. }
  832.  
  833. #####################################################################
  834. ## Log wpa_cli environment variables
  835. wpa_log_env () {
  836.     wpa_msg log "WPA_IFACE=$WPA_IFACE WPA_ACTION=$WPA_ACTION"
  837.     wpa_msg log "WPA_ID=$WPA_ID WPA_ID_STR=$WPA_ID_STR WPA_CTRL_DIR=$WPA_CTRL_DIR"
  838. }
  839.  
  840. #####################################################################
  841. ## hysteresis checking
  842. # Networking tools such as dhcp clients used with ifupdown can
  843. # synthesize artificial ACTION events, particuarly just after a
  844. # DISCONNECTED/CONNECTED events are experienced in quick succession.
  845. # This can lead to infinite event loops, and in extreme cases has the
  846. # potential to cause system instability.
  847. #
  848. wpa_hysteresis_event () {
  849.     echo "$(date +%s)" > "$WPA_CLI_TIMESTAMP" 2>/dev/null
  850. }
  851.  
  852. wpa_hysteresis_check () {
  853.     if [ -f "$WPA_CLI_TIMESTAMP" ]; then
  854.         local TIME
  855.         local TIMESTAMP
  856.         local TIMEWAIT
  857.         TIME=$(date +%s)
  858.         # current time minus 4 second event buffer
  859.         TIMEWAIT=$(($TIME-4))
  860.         # get time of last event
  861.         TIMESTAMP=$(cat $WPA_CLI_TIMESTAMP)
  862.         # compare values, allowing new action to be processed 
  863.         # only if last action was more than 4 seconds ago
  864.         if [ "$TIMEWAIT" -le "$TIMESTAMP" ]; then
  865.             wpa_msg log "$WPA_ACTION event blocked by hysteresis check"
  866.             return 1
  867.         fi
  868.     fi
  869.  
  870.     return 0
  871. }
  872.  
  873. #####################################################################
  874. ## ifupdown locking functions
  875. # A collection of rudimentary locking functions to lock ifup/ifdown
  876. # actions.
  877. #
  878.  
  879. ifupdown_lock () {
  880.     ln -s lock "$WPA_CLI_IFUPDOWN"
  881. }
  882.  
  883. ifupdown_locked () {
  884.     [ -L "$WPA_CLI_IFUPDOWN" ] && return 0
  885.  
  886.     return 1
  887. }
  888.  
  889. ifupdown_unlock () {
  890.     rm -f "$WPA_CLI_IFUPDOWN"
  891. }
  892.  
  893. #####################################################################
  894. ## apply mapping logic and ifup logical interface
  895. # Apply mapping logic via id_str or external mapping script, check
  896. # state of IFACE with respect to ifupdown and ifup logical interaface
  897. #
  898. ifup () {
  899.     local INTERFACES_FILE
  900.     local IFSTATE_FILE
  901.     local IFUP_RETVAL
  902.     local WPA_LOGICAL_IFACE
  903.  
  904.     if [ -e /etc/network/interfaces ]; then
  905.         INTERFACES_FILE="/etc/network/interfaces"
  906.     else
  907.         wpa_msg log "/etc/network/interfaces does not exist, $WPA_IFACE will not be configured"
  908.         return 1
  909.     fi
  910.  
  911.     if [ -e /etc/network/run/ifstate ]; then
  912.         # debian's ifupdown
  913.         IFSTATE_FILE="/etc/network/run/ifstate"
  914.     elif [ -e /var/run/network/ifstate ]; then
  915.         # ubuntu's
  916.         IFSTATE_FILE="/var/run/network/ifstate"
  917.     else
  918.         unset IFSTATE_FILE
  919.     fi
  920.     
  921.     if [ -z "$IF_WPA_MAPPING_SCRIPT_PRIORITY" ] && [ -n "$WPA_ID_STR" ]; then
  922.         WPA_LOGICAL_IFACE="$WPA_ID_STR"
  923.     fi
  924.     
  925.     if [ -z "$WPA_LOGICAL_IFACE" ] && [ -n "$IF_WPA_MAPPING_SCRIPT" ]; then
  926.         local WPA_MAP_STDIN
  927.         
  928.         WPA_MAP_STDIN=$(set | sed -n 's/^\(IF_WPA_MAP[0-9]*\)=.*/echo \$\1/p')
  929.         
  930.         if [ -n "$WPA_MAP_STDIN" ]; then
  931.             WPA_LOGICAL_IFACE=$(eval "$WPA_MAP_STDIN" | "$IF_WPA_MAPPING_SCRIPT" "$WPA_IFACE")
  932.         else        
  933.             WPA_LOGICAL_IFACE=$("$IF_WPA_MAPPING_SCRIPT" "$WPA_IFACE")
  934.         fi
  935.         
  936.         if [ -n "$WPA_LOGICAL_IFACE" ]; then
  937.             wpa_msg log "mapping script result: $WPA_LOGICAL_IFACE"
  938.         else
  939.             wpa_msg log "mapping script failed."
  940.         fi
  941.     fi
  942.  
  943.     if [ -z "$WPA_LOGICAL_IFACE" ]; then
  944.         if [ -n "$IF_WPA_ROAM_DEFAULT_IFACE" ]; then
  945.             WPA_LOGICAL_IFACE="$IF_WPA_ROAM_DEFAULT_IFACE"
  946.         else
  947.             WPA_LOGICAL_IFACE="default"
  948.         fi
  949.     fi
  950.  
  951.     if [ -n "$WPA_LOGICAL_IFACE" ]; then
  952.         if egrep -q "^iface[[:space:]]+${WPA_LOGICAL_IFACE}[[:space:]]+inet" "$INTERFACES_FILE"; then
  953.             : # logical network is defined
  954.         else
  955.             wpa_msg log "network settings not defined for $WPA_LOGICAL_IFACE in $INTERFACES_FILE"
  956.             WPA_LOGICAL_IFACE="default"
  957.         fi
  958.  
  959.         wpa_msg log "ifup $WPA_IFACE=$WPA_LOGICAL_IFACE"
  960.  
  961.         ifupdown_lock
  962.  
  963.         if [ -n "$IFSTATE_FILE" ] && grep -q "^$WPA_IFACE=$WPA_IFACE" "$IFSTATE_FILE"; then
  964.             # Force settings over the unconfigured "master" IFACE
  965.             /sbin/ifup -v --force "$WPA_IFACE=$WPA_LOGICAL_IFACE"
  966.         else
  967.             /sbin/ifup -v "$WPA_IFACE=$WPA_LOGICAL_IFACE"
  968.         fi
  969.         IFUP_RETVAL="$?"
  970.  
  971.         ifupdown_unlock
  972.     fi
  973.  
  974.     wpa_msg log "creating sendsigs omission pidfile: $WPA_SUP_OMIT_PIDFILE"
  975.     cat "$WPA_SUP_PIDFILE" > "$WPA_SUP_OMIT_PIDFILE"
  976.  
  977.     return "$IFUP_RETVAL"
  978. }
  979.  
  980. #####################################################################
  981. ## ifdown IFACE
  982. # Check IFACE state and ifdown as requested.
  983. #
  984. ifdown () {
  985.     wpa_msg log "ifdown $WPA_IFACE"
  986.  
  987.     ifupdown_lock
  988.  
  989.     /sbin/ifdown -v "$WPA_IFACE"
  990.  
  991.     ifupdown_unlock
  992.  
  993.     wpa_msg log "removing sendsigs omission pidfile: $WPA_SUP_OMIT_PIDFILE"
  994.     rm -f "$WPA_SUP_OMIT_PIDFILE"
  995. }
  996.  
  997. #####################################################################
  998. ## keep IFACE scanning
  999. # After ifdown, the IFACE may be left "down", and inhibits 
  1000. # wpa_supplicant's ability to continue roaming.
  1001. #
  1002. # NB: use iproute if present, flushing the IFACE first
  1003. #
  1004. if_post_down_up () {
  1005.     if [ -x /bin/ip ]; then
  1006.         ip addr flush dev "$WPA_IFACE" 2>/dev/null
  1007.         ip link set "$WPA_IFACE" up
  1008.     else
  1009.         ifconfig "$WPA_IFACE" up
  1010.     fi
  1011. }
  1012.