#!/bin/blog

July 7, 2017

How expiration dates in the shadow file really work

Filed under: Uncategorized, UNIX & Linux — Tags: , , , , — martin @ 6:24 pm

tl;dr: Accounts expire as soon as UTC reaches the expiration date.

In today‘s installment of my classic shame-inducing series “UNIX basics for UNIX professionals”, I want to talk about account (and password) expiration in /etc/shadow on Linux.

The expiration time is specified as days since january 1st, 1970. In the case of account expiration, the according value can be found in the second to last field in /etc/shadow.

Account expiration can be configured using the option „-E“ to the „chage“ tool. In this case, I want the user „games“, which I‘ll be using for demonstration purposes, to expire on the 31st of december, 2017:

# chage -E 2017-12-31 games

Using the „-l“ option, I can now list the expiration date of the user:

# chage -l games
[…]
Account expires : Dec 31, 2017
[…]

The first thing to be taken away here is that, as I can only use a number of days, I can not let a user expire at any given time of day. In /etc/shadow, I have now:

# getent shadow | awk -F: '/^games:/{print $8}'
17531

This of course can to be converted to a readable date:

# date --date='1970-01-01 00:00:00 UTC 17531 days'
Sun Dec 31 01:00:00 CET 2017

So, will the account still be usable on december 31st? Let‘s change it‘s expiration to today (the 7th of July, 2017) to see what happens:

# date
Fri Jul 7 12:58:32 CEST 2017
# chage -E today games
# chage -l games
[…]
Account expires : Jul 07, 2017
[…]
# su - games
Your account has expired; please contact your system administrator
[…]

I’m now only left with the question whether this expiration day is aligned on UTC or local time.

# getent shadow | awk -F: '/^games:/{print $8}'
17354
# date --date='1970-01-01 00:00:00 UTC 17354 days'
Fri Jul 7 02:00:00 CEST 2017

I‘ll stop my NTP daemon, manually set the date to 00:30 today and see if the games user has already expired:

# date --set 00:30:00
Fri Jul 7 00:30:00 CEST 2017
# su - games
This account is currently not available.

This is the output from /usr/sbin/nologin, meaning that the account is not expired yet, so I know for sure that the expiration date is not according to local time but to UTC.

Let‘s move closer to our expected threshold:

# date --set 01:30:00
Fri Jul 7 01:30:00 CEST 2017
# su - games
This account is currently not available.

Still not expired. And after 02:00:

# date --set 02:30:00
Fri Jul 7 02:30:00 CEST 2017
# su - games
Your account has expired; please contact your system administrator

So, in order to tell from a script whether an account has expired, I simply need to get the number of days since 1970-01-01. If this number is greater or equal to the value in /etc/shadow, the user has expired.

DAYSSINCE=$(( $(date +%s) / 86400 )) # This is days till now as per UTC.
EXPIREDAY=$(getent shadow | awk -F: '/^games:/{print $8}')
if [[ $DAYSSINCE -ge $EXPIREDAY ]] # Greater or equal
then
    EXPIRED=true
fi

One last thought: We’ve looked at a time zone with a small offset from UTC. What about timezones with larger offsets, in the other direction?

  • If we move the timezone to the east, further into the positive from UTC, it will behave the same as here in CEST and the account will expire sometime during the specified day, when UTC hits the same date.
  • If we move the timezone far to the west, like e.g. PST, and an absolute date is given to “chage -E“, the account will probably expire early, the day before scheduled expiration. I was not able to find anything useful on the web and even my oldest UNIX books from the 1990s mention password expiration only casually, without any detail. Active use of password expiration based on /etc/shadow seems to be uncommon. The code that seems to do the checking is here and it does not appear to care about time zones at all.
  • Any comments that clarify the behaviour in negative offsets from UTC will be appreciated.

January 5, 2016

SSH firewall bypass roundup

Filed under: UNIX & Linux — Tags: — martin @ 8:35 pm

So my SSH workflow has reached a turning point, where I’m going to clean up my ~/.ssh/config. Some entries had been used to leverage corporate firewall and proxy setups for accessing external SSH servers from internal networks. These are being archived here for the inevitable future reference.

I never use “trivial” chained SSH commands, but always want to bring up a ProxyCommand, so I have a transparent SSH session for full port, X11, dynamic and agent forwarding support.

ProxyCommand lines have been broken up for readability, but I don’t think this is supported in ~/.ssh/config and they will need to be joined again to work.

Scenario 1: The client has access to a server in a DMZ

The client has access to a server in an internet DMZ, which in turn can access the external server on the internet. Most Linux servers nowadays have Netcat installed, so this fairly trivial constellation works 95.4% of the time.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh host.dmz /usr/bin/nc -w 60 host.external 22

Scenario 2: As scenario 1, but the server in the DMZ doesn’t have Netcat

It may not have Netcat, but it surely has an ssh client, which we use to run an instance of sshd in inetd mode on the destination server. This will be our ProxyCommand.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh -A host.dmz ssh host.external /usr/sbin/sshd -i

Scenario 2½: Modern version of the Netcat scenario (Update)

Since OpenSSH 5.4, the ssh client has it’s own way of reproducing the Netcat behavior from scenario 1:

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh -W host.external:22 host.dmz

Scenario 3: The client has access to a proxy server

The client has access to a proxy server, through which it will connect to an external SSH service running on Port 443 (because no proxy will usually allow connecting to port 22).

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand /usr/local/bin/corkscrew 
   proxy.server 3128 
   host.external 443 
   ~/.corkscrew/authfile
# ~/.corkscrew/authfile
username:password

(Omit the authfile part, if the proxy does not require authentication.)

Scenario 4: The client has access to a very restrictive proxy server

This proxy server has authentication, knows it all, intercepts SSL sessions and checks for a minimum client version.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand /usr/local/bin/proxytunnel 
   -p proxy.server:3128 
   -F ~/.proxytunnel.auth 
   -r host.external:80 
   -d 127.0.0.1:22 
   -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0\nContent-Length: 0\nPragma: no-cache"
# ~/.proxytunnel.auth
proxy_user=username
proxy_passwd=password

What happens here:

  1. host.external has an apache web server running with forward proxying enabled.
  2. proxytunnel connects to the proxy specified with -r, via the corporate proxy specified with -p and uses it to connect to 127.0.0.1:22, on the forward-proxying apache.
  3. It sends a hand-crafted request header to the intrusive proxy, which mimics the expected client version.
  4. Mind you that although the connection is to a non-SSL service, it still is secure, because encryption is being brought in by SSH.
  5. What we have here is a hand-crafted exploit against the know-it-all proxy’s configuration. Your mileage may vary.

Super sensible discretion regarding the security of your internal network is advised. Don’t fuck up, don’t use this to bring in anything that will spoil the fun. Bypass all teh firewalls responsibly.

October 25, 2014

CentOS 7 on MD-RAID 1

Filed under: UNIX & Linux — Tags: , , , — martin @ 2:47 pm

Figuring this out took me quite a bit of time. In the end, I approached the starter of this hilariously useless CentOS mailing list thread, who assured me that indeed he had found a way to configure MD-RAID in the installer, and behold, here’s how to install CentOS 7 with glorious old-school software RAID.

In the “Installation Destination” screen, select the drives you want to install onto and “I will configure partitioning”. Then click “Done”:
20141025134323In the “Manual Partitioning” screen, let CentOS create the partitions automatically, or create your own partitioning layout. I will let CentOS create them automatically for this test. 20141025134926Apparently due to restrictions in the Installer, /boot is required, but can’t be on a logical volume, so it appears as primary partition /dev/sda1. The root and swap volumes are in a volume group named centos.
The centos volume group will need to be converted to RAID 1 first. Select the root volume and find the “Modify…” button next to the Volume Group selection drop-down. A window will open. In this window, make sure both drives are selected and select “RAID 1 (Redundancy)” from the “RAID Level” drop-down. Repeat this for all volumes in the centos volume group.  If you are using the automatic partition layout, note at this point, how, after this step, the file system sizes have been reduced to half their size.

20141025135637As the final step, select the /boot entry and use the “Device Type” drop-down to convert /boot to a “RAID” partition. A new menu will appear, with “RAID 1 (Redundancy)” pre-selected. The sda1 subscript below the /boot file system will change into the “boot” label once you click anywhere else in the list of file systems.
20141025140445Click “Done”, review the “Summary of Changes”, which should immediately make sense if you have ever configured MD-RAID, and the system will be ready for installation.

October 17, 2014

What does the slash in crontab(5) actually do?

Filed under: UNIX & Linux — Tags: , , , — martin @ 2:16 pm

That’s a bit of a stupid question. Of course you know what the slash in crontab(5) does, everyone knows what it does.

I sure know what it does, because I’ve been a UNIX and Linux guy for almost 20 years.

Unfortunately, I actually didn’t until recently.

The manpage for crontab(5) says the following:

20141017150008

It’s clear to absolutely every reader that */5 * * * * in crontab means, run every 5 minutes. And this is the same for every proper divisor of 60, which there actually are a lot of: 2, 3, 4, 5, 6, 10, 12, 15, 20, 30

However, */13 * * * * does not mean that the job will be run every 13 minutes. It means that within the range *, which implicitly means 0-59, the job will run every 13th minute: 0, 13, 26, 39, 52. Between the :52 and the :00 run will be only 8 minutes.

Up to here, things look like a simple modulo operation: if minute mod interval equals zero, run the job.

Now, let’s look at 9-59/10 * * * *. The range starts at 9, but unfortunately, our naive modulo calculation based on wall clock time fails. Just as described in the manpage, the job will run every 10th minute within the range. For the first time at :09, after which it will run at :19 and subsequently at :29, :39, :49 and :59 and then :09 again.

Let’s look at a job that is supposed to run every second day at 06:00 in the morning: 0 6 */2 * *. The implied range in */2 is 1-31, so the job will run on all odd days, which means that it will run on the 31st, directly followed by the 1st of the following month. The transitions from April, June, September and November to the following months will work as expected, while after all other months (February only in leap years), the run on the last day of the month will be directly followed by one on the next day.

The same applies for scheduled execution on every second weekday at 06:00: 0 6 * * */2. This will lead to execution on Sunday, Tuesday, Thursday, Saturday and then immediately Sunday again.

So, this is what the slash does: It runs the job every n steps within the range, which may be one of the default ranges 0-59, 0-23, 1-31, 1-11 or 0-7, but does not carry the remaining steps of the interval into the next pass of the range. The “every n steps” rule works well with minutes and hours, because they have many divisors, but will not work as expected in most cases that involve day-of-month or day-of-week schedules.

But we all knew this already, didn’t we?

May 11, 2012

Darf man die NTP-Server der PTB nutzen?

Filed under: Internet, UNIX & Linux — Tags: , — martin @ 9:34 am

Auf einer Mailingliste wurde mal wieder die Devise herausgegeben, man solle nicht ohne weiteres die NTP-Zeitserver der Physikalisch-Technischen Bundesanstalt PTB benutzen, sondern stattdessen auf pool.ntp.org zugreifen.

Ich habe diese Geschichte, die schon so lange erzählt wird, wie ich NTP kenne, für eine Urban Legend gehalten und deshalb mal bei der PTB direkt angefragt:

mir läuft schon seit vielen Jahren in Linux- und UNIX-Kreisen ein Ratschlag über den Weg, in dem es heißt, die NTP-Server der PTB seien nicht für die allgemeine öffentliche Nutzung gedacht. Stattdessen solle man sich bei anderen Quellen bedienen, wie z.B. mittlerweile bei pool.ntp.org.

Ich habe selbst leider keine Erfahrungswerte mit NTP-Servern mit Hunderttausenden oder Millionen von Clients, daher kann ich mir selbst keinen Reim darauf machen, wieviel Plausibilität ich dieser Geschichte beimessen soll.

Können Sie mir sagen, ob es für die NTP-Server der PTB irgendwelche Nutzungsbedingungen oder Einschränkungen gibt, die zu beachten sind? Gibt es Auslastungsdaten der Server, die Sie öffentlich machen können?

Daraufhin habe ich sehr schnell die folgende Antwort erhalten:

Gern können Sie unseren NTP-Zeitdienst benutzen. Bitte beachten Sie auch die Hinweise unter:

http://www.ptb.de/de/org/q/q4/q42/ntp/ntp_main.htm

Grundsätzlich sind unsere NTP-Server für die allgemeine Nutzung freigegeben. Die Auslastungsdaten stellen wir nicht öffentlich bereit. Derzeit ist es jedoch so, dass uns pro Sekunde mehrere Tausend Abfragen auf dem NTP-Port erreichen. Diese stellen aber kein Problem dar! Problematischer sind nur die Abfragen auf dem Time- und Daytime-Port, die wir daher begrenzen.

Sprich: Jedermann kann die NTP-Server der PTB ohne weiteres benutzen, um die gesetzliche Zeit der Bundesrepublik Deutschland zu beziehen. Meine Theorie, daß es sich bei den vermuteten Einschränkungen hinsichtlich ihrer Nutzbarkeit um Urban Legends handelt, war also zutreffend. 🙂

March 3, 2012

Das Ende von Linux auf dem Desktop

Filed under: UNIX & Linux — martin @ 10:54 am

Mir ist, kurz gesagt, ziemlich egal, von welchem Betriebssystem meine Bash, mein Firefox und mein LaTeX geladen werden.

Und so schwänze ich schon seit bald einem Jahr die Treffs “meiner” Linux User Group, und beteilige mich auf der Mailingliste nicht mehr, weil ich dort konstant dafür angemacht werde, daß ich unterwegs ein Macbook Air mit Mac OS X benutze.

Jetzt hat es endlich den guten Linus Torvalds auf Google Plus erwischt. Er schrieb über seine Unzufriedenheit mit OpenSUSE und darüber, daß er wohl eine andere Distribution suchen muß, die auf dem Macbook Air einigermaßen rund läuft:

I gave OpenSUSE a try, because it worked so well at install-time on the Macbook Air, but I have to say, I’ve had enough. […]
.. and now I need to find a new distro that actually works on the Macbook Air.

Hier einige der Expertenratschläge, die er darauf erhalten hat:

“It’s pretty strange that you have a Macbook Air. One leader of free software having something very closed it’s kinda disturbing.”

“I agree, but Macbook Air? Why, oh why…please get some real hardware for men…”

“Seriously, a “Macbook Air”? Might I ask, WHY? So much for principle….”

“Who uses/buys a mac anyways?”

“why is Linus using a mac?”

“Why would you use Apple hardware anyway… :/”

“Why would you use Mac? Just get Windows, and install Linux over it, something I don’t think you can do on a Mac. Even with BootCamp.”


Der Linux-Desktop wird heute von einem Großteil seiner Nutzer instrumentalisiert, um sich selbst eine vermeintliche moralische Überlegenheit gegenüber denjenigen zu verschaffen, die vermeintlich unreflektiert einfach konsumieren, was ihnen angeboten wird. Ich wurde mit einer Diskussion über Morallosigkeit konfrontiert, weil ich ein Macbook besitze. Ob jemand den ganzen Tag 1000 Linuxserver von einer Linuxworkstation administriert, oder ob er verdammt nochmal Linus Torvalds selbst ist, spielt für diese Extremisten keine Rolle.

Mit diesem oberflächlichen Linuxzirkus, mit dieser destruktiven Feindseligkeit, bringt ihr Linux auf dem Desktop nicht voran, sondern drängt es im Gegenteil noch weiter in die Nische, aus der es schon seit 20 Jahren nur ab und an zögerlich die Nase herauszustecken versucht.

Und dabei ist Linux nur ein Kernel. Linux ist vielleicht für Linus Torvalds wichtig, muß es für uns aber nicht sein. Was zählen muß, sind übergreifende Dateiformate, offene Protokolle und freie Software.

Wer aber freie Software konstruktiv voranbringen will, darf niemanden wegen eines Teils seines Stacks ausgrenzen.

June 3, 2011

Rebootless kernel updates

Filed under: UNIX & Linux — Tags: , , — martin @ 9:34 pm

It’s been a while since my last post, and this time, for a change, I have decided to produce a screencast. In which I show you what rebootless linux kernel updates with the great service from Ksplice actually look like.

This is on one of two Ubuntu 10.04 LTS system, for which I have licensed the commercial Ksplice service.

P.S.: Sorry for inflicting my foul accent upon you. 😉

April 14, 2011

Bind OpenLDAP slapd to localhost only (on RHEL/CentOS)

Filed under: UNIX & Linux — Tags: , , — martin @ 9:24 am

Implemented on RHEL5.

In /etc/sysconfig/ldap, append:

SLAPD_OPTIONS="-h \"ldap://127.0.0.1 ldaps://127.0.0.1\""

Then issue /etc/init.d/ldap restart.

January 30, 2011

Make directory immutable on Linux

Filed under: UNIX & Linux — Tags: , , — martin @ 1:26 pm

Most of you know the immutable flag on Linux filesystems. It marks a given file in a special way that not even root can accidentally delete or modify it:

# touch /tmp/foo
# chattr +i /tmp/foo
# rm /tmp/foo
rm: cannot remove `/tmp/foo': Operation not permitted

Unfortunately it is not possible to apply the same to a directory so it can never be deleted, even when it is empty. At least not, if the directory is supposed to be usable for anything, because immutability means that there can be no files written to it:

# mkdir /tmp/foo
# chattr +i /tmp/foo
# touch /tmp/foo/bar
touch: cannot touch `/tmp/foo/bar': Permission denied

My workaround is to create a hidden file in the directory and make it immutable:

# mkdir /tmp/foo
# touch /tmp/foo/.immutable
# chattr +i /tmp/foo/.immutable
# rm -rf /tmp/foo
rm: cannot remove `/tmp/foo/.immutable': Operation not permitted

December 7, 2010

Set default ACL on Linux

Filed under: UNIX & Linux — martin @ 2:45 pm

Challenge: User1 has a world-writable directory. User2 has umask 077 set and writes into User1’s world writable directory. User1 can’t read those files.

Workaround: Short of User 2 setting his umask properly, set a default ACL on the directory:

setfacl -d -m user::rw,group::rw,other::r /path/to/User1/incoming/

Older Posts »

Create a free website or blog at WordPress.com.