Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 176770) +++ channels/chan_sip.c (working copy) @@ -1067,6 +1067,7 @@ enum transfermodes allowtransfer; /*!< SIP Refer restriction scheme */ int allowsubscribe; /*!< Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE the global setting is in globals_flags[1] */ + int minimumpasswordstrength; /*!< Disable accounts with weak passwords */ char realm[MAXHOSTNAMELEN]; /*!< Default realm */ struct sip_proxy outboundproxy; /*!< Outbound proxy */ char default_context[AST_MAX_CONTEXT]; @@ -2306,6 +2307,7 @@ int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_peer **authpeer); static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin); +static int password_strength(const char *secret); /*--- Domain handling */ static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */ @@ -4317,6 +4319,35 @@ return newpeername; } +static int password_strength(const char *secret) +{ + int upper = 0, lower = 0, digit = 0, punct = 0, length = 0; + int len; + if (secret == NULL) { + return 0; + } + if ((len = strlen(secret)) < 8) { + length = 0; + } else if (len < 16) { + length = 1; + } else { + length = 2; + } + + for (; *secret; secret++) { + if (isupper(*secret)) { + upper = 1; + } else if (islower(*secret)) { + lower = 1; + } else if (isdigit(*secret)) { + digit = 1; + } else if (ispunct(*secret)) { + punct = 1; + } + } + return upper + lower + digit + punct + length; +} + /*! \brief realtime_peer: Get peer from realtime storage * Checks the "sippeers" realtime family from extconfig.conf * Checks the "sipregs" realtime family from extconfig.conf if it's configured. @@ -11674,6 +11705,11 @@ if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) return AUTH_SUCCESSFUL; + /* If the password is considered weak, it always fails */ + if (!sip_cfg.minimumpasswordstrength && ast_strlen_zero(md5secret) && password_strength(secret) < sip_cfg.minimumpasswordstrength) { + return AUTH_SECRET_FAILED; + } + /* Always auth with WWW-auth since we're NOT a proxy */ /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ response = "401 Unauthorized"; @@ -23186,6 +23222,7 @@ global_timer_b = 64 * SIP_TIMER_T1; global_t1min = DEFAULT_T1MIN; global_qualifyfreq = DEFAULT_QUALIFYFREQ; + sip_cfg.minimumpasswordstrength = 4; sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY; @@ -23214,6 +23251,8 @@ global_callcounter = ast_true(v->value) ? 1 : 0; } else if (!strcasecmp(v->name, "allowguest")) { sip_cfg.allowguest = ast_true(v->value) ? 1 : 0; + } else if (!strcasecmp(v->name, "minimumpasswordstrength")) { + sip_cfg.minimumpasswordstrength = atoi(v->value); } else if (!strcasecmp(v->name, "realm")) { ast_copy_string(sip_cfg.realm, v->value, sizeof(sip_cfg.realm)); } else if (!strcasecmp(v->name, "useragent")) { Index: configs/sip.conf.sample =================================================================== --- configs/sip.conf.sample (revision 176770) +++ configs/sip.conf.sample (working copy) @@ -185,6 +185,9 @@ ;disallow=all ; First disallow all codecs ;allow=ulaw ; Allow codecs in order of preference ;allow=ilbc ; see doc/rtp-packetization for framing options +;minimumpasswordstrength=4 ; Judge passwords by their relative strength. + ; Longer is better, as is including letters and + ; punctuation. [0-6, default 4] ; ; This option specifies a preference for which music on hold class this channel ; should listen to when put on hold if the music class has not been set on the