Note: You are viewing an old version of this page. View the current version.

#!/bin/sh

passwdhost="owa.example.com/owa"

init() {
  cookiejar="$(mktemp cookie.jar.XXXXXXXX)"
  certstore="$(mktemp gd_bundle.crt.XXXXXXXX)"
  cat > "${certstore}" <<EOF
-----BEGIN CERTIFICATE-----
MIIFIDCCBAigAwIBAgIQRscnw5bZXG06EIMM4UWsrjANBgkqhkiG9w0BAQUFADCB
sDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug
YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNTEqMCgGA1UEAxMh
VmVyaVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBMB4XDTA4MDMwMzAwMDAw
MFoXDTEwMDMwMzIzNTk1OVowgZMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVUZXhh
czETMBEGA1UEBxQKRm9ydCBXb3J0aDEpMCcGA1UEChQgQ2FzaCBBbWVyaWNhIElu
dGVybmF0aW9uYWwsIEluYy4xGzAZBgNVBAsUEk5ldHdvcmsgT3BlcmF0aW9uczEX
MBUGA1UEAxQOb3dhLmNhc2hhbS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
AoGBAKNU+cBxNwM417bLTNT8b3pBn4GAwwedm1l/fUHuqBD6RXgEXXrbRUBKWpbn
yvVk/38721hwSxpkTpZBIlHfgRA0bx9aQtCZKlD3a3C5Vk67QqRakEiBu5aNveou
6jjIj+wgqa79je4SaG8QS9N3nEnPiB9mub+G3/OrnqxE5PCzAgMBAAGjggHTMIIB
zzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDBEBgNVHR8EPTA7MDmgN6A1hjNodHRw
Oi8vU1ZSU2VjdXJlLWNybC52ZXJpc2lnbi5jb20vU1ZSU2VjdXJlMjAwNS5jcmww
RAYDVR0gBD0wOzA5BgtghkgBhvhFAQcXAzAqMCgGCCsGAQUFBwIBFhxodHRwczov
L3d3dy52ZXJpc2lnbi5jb20vcnBhMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjAfBgNVHSMEGDAWgBRv7K+g3Yqk7/UqEGctP1WCvNfvJTB5BggrBgEFBQcB
AQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnZlcmlzaWduLmNvbTBDBggr
BgEFBQcwAoY3aHR0cDovL1NWUlNlY3VyZS1haWEudmVyaXNpZ24uY29tL1NWUlNl
Y3VyZTIwMDUtYWlhLmNlcjBuBggrBgEFBQcBDARiMGChXqBcMFowWDBWFglpbWFn
ZS9naWYwITAfMAcGBSsOAwIaBBRLa7kolgYMu9BSOJsprEsHiyEFGDAmFiRodHRw
Oi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvMS5naWYwDQYJKoZIhvcNAQEFBQAD
ggEBAI+wusO7VsNCS149VUlxypCJfm94/5edrAz0gvRWqDA1sOwUDZDsu6f3ugai
47ggcLi/2FG4bf8nwndG1x1KwmC7TgUnmIXXAm0lXipeDUa0scP9vex3N4YR5yqS
Swvetveg3Cc/8GAR/wHjCs/pLD1Fh1zpo2+Y525Fm2StByGPI5ayLrI+ZDauc6Ci
WRgYUaXRkzfX84FOzxMcIBfcUUPVtelpefazujtN/KRja+Q1v4ZJgjuj9ixK0ItL
ZN1eXIY7+Shcv3JmAPOz1KsgNLrk7BitJ9OyrdXEsNOKC/usfZwyFa4Stpig0P+W
N23ILAQBYggPjzGi6pvxtBGyDMM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEnDCCBAWgAwIBAgIQdTN9mrDhIzuuLX3kRpFi1DANBgkqhkiG9w0BAQUFADBf
MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT
LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
HhcNMDUwMTE5MDAwMDAwWhcNMTUwMTE4MjM1OTU5WjCBsDELMAkGA1UEBhMCVVMx
FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
dCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cu
dmVyaXNpZ24uY29tL3JwYSAoYykwNTEqMCgGA1UEAxMhVmVyaVNpZ24gQ2xhc3Mg
MyBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAlcMhEo5AxQ0BX3ZeZpTZcyxYGSK4yfx6OZAqd3J8HT732FXjr0LLhzAC3Fus
cOa4RLQrNeuT0hcFfstG1lxToDJRnXRkWPkMmgDqXkRJZHL0zRDihQr5NO6ziGap
paRa0A6Yf1gNK1K7hql+LvqySHyN2y1fAXWijQY7i7RhB8m+Ipn4G9G1V2YETTX0
kXGWtZkIJZuXyDrzILHdnpgMSmO3ps6wAc74k2rzDG6fsemEe4GYQeaB3D0s57Rr
4578CBbXs9W5ZhKZfG1xyE2+xw/j+zet1XWHIWuG0EQUWlR5OZZpVsm5Mc2JYVjh
2XYFBa33uQKvp/1HkaIiNFox0QIDAQABo4IBgTCCAX0wEgYDVR0TAQH/BAgwBgEB
/wIBADBEBgNVHSAEPTA7MDkGC2CGSAGG+EUBBxcDMCowKAYIKwYBBQUHAgEWHGh0
dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwMQYDVR0fBCowKDAmoCSgIoYgaHR0
cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwDgYDVR0PAQH/BAQDAgEGMBEG
CWCGSAGG+EIBAQQEAwIBBjApBgNVHREEIjAgpB4wHDEaMBgGA1UEAxMRQ2xhc3Mz
Q0EyMDQ4LTEtNDUwHQYDVR0OBBYEFG/sr6DdiqTv9SoQZy0/VYK81+8lMIGABgNV
HSMEeTB3oWOkYTBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIElu
Yy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHmCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQEFBQADgYEA
w34IRl2RNs9n3Nenr6+4IsOLBHTTsWC85v63RBKBWzFzFGNWxnIu0RoDQ1w4ClBK
Tc3athmo9JkNr+P32PF1KGX2av6b9L1S2T/L2hbLpZ4ujmZSeD0m+v6UNohKlV4q
TBnvbvqCPy0D79YoszcYz0KyNCFkR9MgazpM3OYDkAw=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
-----END CERTIFICATE-----
EOF
  trap "rm -f '${cookiejar}' '${certstore}'" exit hup int term kill
}

meh() {
  printf "%s\n" "${*}" >&2
}

omg() {
  [ "${#}" -gt 0 ] && printf "\n%s\n" "${*}" >&2
  exit 1
}

pebkac() {
  if [ "${#}" -gt 0 ]
  then
    meh "${*}"
    meh ""
  fi
  meh "Usage: $(basename "${0}") <username> <password> [times]"
  meh "This utility will shuffle your Exchange password via Outlook Web Access"
  meh "through an arbitrary  number of resettings, to thwart silly"
  meh "password reusage restrictions."
  meh ""
  meh ""
  meh "******* WARNING ********"
  meh "This script will RESET YOUR PASSWORD!"
  meh "PAY ATTENTION to the output! If it fails halfway through, you will NEED to"
  meh " know the last password it was successfully set to, so you can fix it yourself!"
  meh " If you do not pay attention, expect to contact helpdesk for a password reset."
  meh "******* WARNING ********"
  meh ""
  omg
}

take_cannoli() {
  user="${1}"
  pass="${2}"
  post="${3}"

  cmd="$(printf '/usr/bin/wget -qO- --ca-certificate="%s" --load-cookies="%s" --save-cookies="%s" --keep-session-cookies --http-user="%s" --http-password="%s" "https://${passwdhost}/?ae=Options&t=ChangePassword"' "${certstore}" "${cookiejar}" "${cookiejar}" "${user}" "${pass}")"
  [ -n "${post}" ] && cmd="${cmd}""$(printf ' --post-data="%s"' "${post}")"

  res="$(eval "${cmd}")"
  _res=$?

  if [ "${_res}" -gt 0 ]
  then
    meh "Service error: failed with status ${_res}"
    return "${_res}"
  fi

  echo "${res}"

  error="$(echo "${res}" | grep 'dvErr' | sed -e 's/^.*<h1>\([^<]*\)<.*$/\1/')"
  if [ "${error}" ]
  then
    meh "${error}"
    return 1
  fi

  return 0
}

steal_canary() {
  take_cannoli "${user}" "${pass}" | sed -e 's/^.*name="hidcanary" value="\([^"]*\)".*$/#\1/; /^[^#]/d; s/^#//'
}

chpass() {
  user="${1}"
  pass="${2}"
  newpass="${3}"

  canary=$(steal_canary)
  [ -z "${canary}" ] && return 1
  echo "Got canary ${canary}"
  post="$(printf 'hidpnst=&txtOldPwd=%s&txtNewPwd=%s&txtConfirmPwd=%s&hidcmdpst=save&hidcanary=%s' "${pass}" "${newpass}" "${newpass}" "${canary}")"
  res=$(take_cannoli "${user}" "${pass}" "${post}")
  _res="${?}"
  return "${_res}"
}

owa_passwd() {
  username="${1}"
  password="${2}"
  times="${3:-5}"

  [ "${username}" -a "${password}" ] || pebkac
  case "${times}" in
  [0-9]*)
    true ;;
  *)
    pebkac "'times should be an integer" ;;
  esac

  init

  oldpass="${password}"
  newpass=""
  for iter in $(seq 1 "${times}")
  do
    newpass="$(printf '%s_%02u' "${password}" "${iter}")"
    echo "chpass: ${oldpass} -> ${newpass}"
    chpass "${username}" "${oldpass}" "${newpass}" || return 1
    sleep 1
    oldpass="${newpass}"
  done
  echo "chpass ${oldpass} -> ${password}"
  chpass "${username}" "${oldpass}" "${password}" || return 1
  return 0
}

[ "${1}" = '-h' ] && pebkac
owa_passwd "${@}" || omg "Something failed! Read the errors carefully!"