# -*- Fundamental -*-
# (C) 2004 Michel Arboi <mikhail@nessus.org>


# http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
# [epoch:]upstream_version[-debian_revision]

include('global_settings.inc');

function deb_str_cmp(s1, s2)
{
 local_var	v1, v2;

 while (s1 || s2)
 {
  v1 = eregmatch(string: s1, pattern: "^([^0-9]*)([0-9]*)(.*)$");
  v2 = eregmatch(string: s2, pattern: "^([^0-9]*)([0-9]*)(.*)$");
  if (v1[1] < v2[1])
   return -1;
  else if (v1[1] > v2[1])
   return 1;
  if (v1[2] != v2[2]) return int(v1[2]) - int(v2[2]);
  s1 = v1[3]; s2 = v2[3];
 }
 return 0;
}

function deb_ver_cmp(ver1, ver2)
{
 local_var	v1, v2, e1, e2, uv1, uv2, dr1, dr2, x;

 v1 = eregmatch(string: ver1, pattern: "^([0-9]+:)?(.+)(-([a-z0-9+.]+))?$", icase: 1);
 v2 = eregmatch(string: ver2, pattern: "^([0-9]+:)?(.+)(-([a-z0-9+.]+))?$", icase: 1);
 if (isnull(v1) || isnull(v2)) return NULL;
 e1 = int(v1[1]); uv1 = v1[2]; dr1 = v1[4];
 e2 = int(v2[1]); uv2 = v2[2]; dr2 = v2[4];

 if (e1 != e2) return e1 - e2;
 x = deb_str_cmp(s1: uv1, s2: uv2);
 if (x) return x;
 x = deb_str_cmp(s1: dr1, s2: dr2);
 return x; 
}


function deb_check(prefix, release, reference)
{
 local_var debver, dpkg_l, pkgver;
 local_var installed, ver, v;

 debver = chomp(get_kb_item("ssh/login/release"));
 if ( ! debver ) return 0; # Not debian

# Try something smarter but slower below
## if (debver && release != debver) return 0;

 dpkg_l = get_kb_item("ssh/login/packages");
 installed = egrep(string: dpkg_l, pattern: '^ii +' + prefix + ' +');
 if (! installed) return 0;
 ver = ereg_replace(	string: installed, replace: "\1",
			pattern: '^ii +' + prefix + ' +([^ ]+) +.*$');
 if (ver == installed) return 0;	# cannot extract version

# Here, we try to extract the "branch" from the installed package
# I don't think that mixing sarge, woody and sid packages on a single
# system is great, but it is possible.
# However, the branch is not always included in the package name, and
# Look at "DSA 865-1" for example. So we fall back to /etc/debian-release
# and hope that such mix did not occur

 if (ereg(string: ver, pattern: '[0-9]$')) pkgver = debver; # or '4.0'?
 else if (ereg(string: ver, pattern: 'etch[0-9]$')) pkgver = '4.0';
 else if (ereg(string: ver, pattern: 'sarge[0-9]$')) pkgver = '3.1';
 else if (ereg(string: ver, pattern: 'woody[0-9]$')) pkgver = '3.0';
 else if (ereg(string: ver, pattern: 'potato[0-9]$')) pkgver = '2.2';
 else if (ereg(string: ver, pattern: 'hamm[0-9]$')) pkgver = '2.0';
 else pkgver = debver;

 # This is a dirty work around that fixes at least for 3.1
 release = strcat('DEB', release);

 if (pkgver && release != pkgver) return 0;

 if (deb_ver_cmp(ver1: ver, ver2: reference) < 0)
 {
   debug_print("debian_package[", get_host_ip(), "]: package ", prefix, "_", ver, " is vulnerable in Debian ", release, ". Upgrade to ", prefix, "_", reference, "\n");
   return 1;
 }
 return 0;
}
