What kind of data can you extract from a UUID? - uuid

I know that we could easily extract the uuid version number. Is there a reliable way to extract information like timestamp, MAC address?
Thanks!

A standard-conforming UUID may be one of several variants, it looks like this:
AAAAAAAA-BBBB-CCCC-DDDD-FFFFFFFFFFFF
The first (hex)digit of the DDDD part determines the variant.
If it is one of 8,9,A,B it is conforming to the current spec
(0-7 are reserved for backward compatibility, C,D are reserved for Microsoft, and E,F are reserved for future use)
If it conforms to the current spec, check the first digit of the CCCC part which determines the UUID version:
Time-based with unique or random host identifier (MAC)
DCE Security version (with POSIX UIDs)
Name-based (MD5 hash)
Random
Name-based (SHA-1 hash)
Version 4 is simply randomly chosen.
Version 3 and 5 are generated by hashing and throwing away some bits which means you have basically no chance in recovering any information from it. Details on how to build it can be found in RFC4122 or at the UUID Generator webpage.
I could not find any version 2 UUIDs so I didn't check how to extract the data.
Version 1 is generated from a time-stamp and current host MAC address.
(The standard also allows to use a random address instead if you set the "broadcast/multicast" bit of the MAC address.)
The following perl snipped parses the MAC address and Time from a version 1 uuid:
my $uuid="AAAAAAAA-BBBB-CCCC-DDDD-FFFFFFFFFFFF";
$uuid=~tr/-//d;
my $time_low=hex substr($uuid,2* 0,2*4);
my $time_mid=hex substr($uuid,2* 4,2*2);
my $version =hex substr($uuid,2* 6,1);
my $time_hi =hex substr($uuid,2* 6+1,2*2-1);
my $time=($time_hi*(2**16)+$time_mid)*(2**32)+$time_low;
my $epoc=int($time /10000000) - 12219292800;
my $nano=$time-int($time/10000000)*10000000;
my $clk_hi =hex substr($uuid,2* 8,2*1);
my $clk_lo =hex substr($uuid,2* 9,2*1);
my $node =substr($uuid,2*10,2*6);
$node=~/^(..)(..)(..)(..)(..)(..)$/ || die;
$node="$1:$2:$3:$4:$5:$6";
print "time: ",scalar localtime $epoc," +",$nano/10000,"ms\n";
print "clock id: ",$clk_hi*256+$clk_lo,"\n";
print "Mac: $node\n";
my $byte=hex $1;
if(hex($1)&1){
print "broadcast/multicast bit set.\n";
};
And last but not least, there are several assigned UUIDs, for example for GPT partitions.

Not necessarily a reliable way, because depending on the kind of UUID it is, it may be generated totally from random bits, or be timestamp-based, or be based on the MAC address. So you may be able to get some of that information, but you can't guarantee you can get anything.
The official reference for this is RFC 4122, which should probably give you enough information to extract data, although you probably shouldn't rely on it too heavily.

I know that we could easily extract the uuid version number. Is there a reliable way to extract information like timestamp, MAC address?
Yes, and Yes; if the UUID is version 1 or version 2 (as described in RFC 4122). There is also an alternate (non-RFC 4122) version 4, dubbed "COMB" that includes a time-stamp (as well as random values) that can be parsed, and the creation date/time can be revealed.
Bonus: Mahonri Moriancumer's UUID and GUID Generator and Forensics.

The OSSP uuid tool can decode UUIDs of all versions. On Debian-based Linux systems you can use apt-get install uuid to install it; for other distributions, the package name might be different.
To decode a UUID, use the -d (decode) flag:
uuid -d AAAAAAAA-BBBB-CCCC-DDDD-FFFFFFFFFFFF
For version 1 UUIDs, this gives the MAC address and timestamp -- since that's what's in a v1 uuid.

If it's a version 1 UUID, the MAC address will be the last twelve hex digits.

You could look at the version of the Uuid, but that can only be trusted if you are sure the Uuid is valid (see https://www.rfc-editor.org/rfc/rfc4122). The version will tell you what kind of Uuid you have, and using that you can extract specific bits of information.

Related

Question of Vendor ID in RFC2408 (ISAKMP)

I am reading the RFC2408(https://www.rfc-editor.org/rfc/rfc2408). I have a question about "Vendor ID section" at page 43(https://www.rfc-editor.org/rfc/rfc2408#page-43).
The document says,
For instance:
"Example Company IPsec. Version 97.1"
(not including the quotes) has MD5 hash:
48544f9b1fe662af98b9b39e50c01a5a, when using MD5file.
But I use many md5 tools like 'md5sum' command or online tools, that they all got result "3245b3577c9e4f751675322f259ff016".
I tried the command on Linux:
echo -n "Example Company IPsec. Version 97.1" | md5sum
3245b3577c9e4f751675322f259ff016 -
I got different result, I believe the RFC ducument would not be wrong, So I wonder where am I wrong, or do I miss some thing?
The MD5 hash is actually of the value:
Example Company IPsec. Version 97.1\n
That is, only one space separates IPsec. and Version and there is a newline character at the end.
So you get this with:
echo "Example Company IPsec. Version 97.1" | md5sum
48544f9b1fe662af98b9b39e50c01a5a -
Please note two things:
While th vendor ID values must be unique, they are otherwise completely arbitrary. This is just an example of how one might be generated. So its correctness is not really relevant.
ISAKMP/IKEv1 has been obsolete for years, please refer to IKEv2 instead (RFC 7296).

Dart - How can I get the creationTime of a File?

I need to get the creationTime of a File in my Flutter project but all I have from a File object is lastModified() and lastAccessed(), no trace of a method to get the DateTime of creation.
I see that in Java it is possible: https://stackoverflow.com/a/2724009/3997782
and also in Swift: https://stackoverflow.com/a/6428757/3997782
I could use the Flutter MethodChannel function to get that but I would like to know if there a native Dart way to get it.
How to get the local file information, such as file creation time
Not all platforms does have a concept of file creation time. E.g. Linux does not for all file systems and the general stat() call does not provide that information.
That does not mean you cannot access what seems to be creation time. But you should not necessarily trust its value which are also documented in the Java API:
Returns the creation time. The creation time is the time that the file was created.
If the file system implementation does not support a time stamp to indicate the time when the file was created then this method returns an implementation specific default value, typically the last-modified-time or a FileTime representing the epoch (1970-01-01T00:00:00Z).
https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/BasicFileAttributes.html#creationTime()
Dart does have a similar API if you use the FileStat class which have this property:
DateTime changed
The time of the last change to the data or metadata of the file system object.
On Windows platforms, this is instead the file creation time.
https://api.dart.dev/stable/2.7.2/dart-io/FileStat/changed.html
But the data for FileStat is documented to come from the POSIX stat() system call which does not have a concept of creation timestamp of files but has the following:
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
Which maps to the three timestamps you can get from FileStat:
import "dart:io";
main() {
final stat = FileStat.statSync("test.dart");
print('Accessed: ${stat.accessed}');
print('Modified: ${stat.modified}');
print('Changed: ${stat.changed}');
}
But as you can see on Linux with XFS it will return the same value for changed and modified:
[julemand101#beta ~]$ dart test.dart
Accessed: 2020-04-07 18:19:20.404
Modified: 2020-04-07 18:19:19.020
Changed: 2020-04-07 18:19:19.020
You can get a different changed time if you e.g. update inode information:
[julemand101#beta ~]$ chmod +x test.dart
[julemand101#beta ~]$ dart test.dart
Accessed: 2020-04-07 18:19:42.341
Modified: 2020-04-07 18:19:19.020
Changed: 2020-04-07 18:19:39.397
Which makes sense since the st_ctime is documented as:
The field st_ctime is changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.).
https://linux.die.net/man/2/stat
So in short, you should try and see what happens for iOS and Android when using FileStat. But in short, it is difficult to write a platform independent API which gives access to differences at each platform. Especially for a platform like Linux where it is up to each file system if a feature exists or not.

write custom timestamp into syslog using syslog.h

my program get events from remote systems, every event contains an timestamp.
I want to log this events to syslog using the event timestamp instead of systemtime.
Is there any way to send a custom header to syslog deamon ?
I'm using rsyslog on debian
EDIT:
The "events" are generated by some "bare-metal" devices.
My application is a gateway between a realtime-ethernet (EthernetPOWERLINK) and a normal network.
I want to save them in micro-second precision, because its important to know in wich sequence they are occoured.
So i need the exact timestamp created by the bare-metal devices.
I'like to put this events into syslog.
I did not found any lib (except syslog.h) to write into syslog).
I really need to build the packages myself and send them to rsyslog deamon ?
No, don't open that can of worms.
If you allow the sender to specify the timestamp, you allow an attacker to spoof the timestamps of events they wish to hide. That kind of defeats the entire purpose (security-wise) of using a separate machine for logging.
What you can do, however, is compare the current time and the timestamp, and include that at the start of every logged message, using something like
struct timespec now;
struct timespec timestamp;
double delta;
int priority = facility | level;
const char *const message;
delta = difftime(timestamp.tv_sec, now.tv_sec)
+ ((double)timestamp.tv_nsec - now.tv_nsec) / 1000000000.0;
syslog(priority, "[%+.0fs] %s\n", delta, message);
On a typically configured Linux machine, that should produce something similar to
Jan 18 08:01:02 hostname service: [-1s] Original message
assuming the message took at least half a second to arrive. If hostname has its clock running fast, the delta would be positive. Normally, the delta is zero. In the case of a very slow network, the delta is negative, since the original event happened in the past relative to the timestamp shown.
If you already have infrastructure in place to monitor the logged messages, you can have a daemon or a cron script read the log files, and generate new log files (not via syslog(), but simply with string and file operations) with the timestamps adjusted by the specified delta. However, that must be done with extreme care, recognizing unacceptable or unexpectedly changing deltas, or maybe flagging them somehow.
If you write your log file monitoring/display widgets, then you can very easily let the user switch between "actual" (syslog) or "derived" (syslog + delta) timestamps, as the delta is trivial to extract from the logged lines if always present; even then, you must be careful to let the user know if a delta is out of bounds or changes unexpectedly, as such a change is most always informative to the user. (If it is not nefarious, it does mean there is something iffy with the machine timekeeping; time should not just jump around. Even NTP adjustments should be quite smooth.)
If you insist on opening that can of worms, just produce your own log files. Many applications do. It's not like syslog() was a magic bullet or a strict requirement for reliable logging, after all.
If your log-receiving application runs as a specific user and group, you can create /var/log/yourlogs/ owned by root user and that group, and save your log files there. Set the directory mode to 02770 (drwxrws--- or u=rwx,g=rwxs,o=), and all files created in that directory will automatically be owned by the same group (that's what the setgid bit, s, does for directories). You just need to make sure your service sets umask to 002 (and uses 0666 or 0660 mode flags when creating log files), so that they stay group-readable and group-writable.
Log rotation (archiving and/or deleting old log files, mailing logs) is usually a separate service, provided by the logrotate package, and configured by dropping a service-specific configuration file in /etc/logrotate.d/ at installation time. In other words, even if you write your own log files, do not rotate them; use the existing service for this. It makes life much easier for your users, us system administrators. (Note: Setting umask 002 at the start of the log rotate scripts is very useful in the above directory case; created files will then be group-writable. umask 022 will make them group-read-only.)
Ok've solved this, by enabling networking support (TCP) and micro seconds timer in rsyslog configuration.
Accroding to RFC 5424 my application build raw syslog messages and sends them via TCP (port 514) to the deamon.
Thanks to Nominal Animal, but i've no choice...
You can write a raw log message to the /dev/log file. This is a Unix domain socket from where the syslog server reads the messages, as they are written with the syslog() function.
I'm not sure about portability since the message format written by syslog() does not seem to follow the RFC 5424. I can only share my findings with busybox and its syslogd and nc utilities.
syslog() function writes messages as datagrams in the form <PRI>Mon DD HH:MM:SS message, where PRI is a priority, i.e. a decimal number computed as facility | severity, followed by a timestamp and a message.
With nc -u local:/dev/log, you can write UDP datagrams to the domain socket directly. For example, writing <84>Apr 3 07:27:20 hello world results in a Apr 3 07:27:20 hostname authpriv.warn hello world line in /var/log/messages.
Then you are free to extend the timestamp with the microseconds precision. Anyway, you need to make sure your syslog server implementation accepts such form. In case of busybox, I had to modify the source code.
Note: Busybox needs to be configured with enabled CONFIG_NC_EXTRA, CONFIG_NC_110_COMPAT and CONFIG_FEATURE_UNIX_LOCAL options to allow for opening /dev/log with nc.

How to get os name, version in windows?

Which one is better in following aspects to get OS name, OS version in windows -
time in getting information
compatibility in all windows OS like xp, vista and higher
systeminfo or wmic command? I wanted to avoid the use of OSVersionInfoEx in C as one has to hardcode the marketing name detection and will add to maintenance work if new flavour of windows gets introduced. Please share your opinion.
GetVersionEx - You can't get any faster than this for getting a basic os version number. But you are right, you won't be able to map newer versions of the OS to the correct string. Have you considered just doing this:
OSVERSIONINFOEX version = {};
char szOS[MAX_OS_LENGTH];
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx((OSVERSIONINFO*)&version);
if (MyFunctionToMapVersionToString(&version, szOS) == false)
{
sprintf(szOS, "Microsoft Windows %d.%d", version.dwMajorVersion, version.dwMinorVersion);
}
WMI - A bit more code to write. But you could likely just do this at app startup (or when it's needed) and cache the result if the information is needed again. It's not like the operating system product name will change after the app has queried for it once. :) As to backwards compatibility, I'm sure it work fine on older operating systems... but you are going to test it before shipping it to the customer, right?
If you want an undocumented way, there is a registry key that has exactly what you want in it:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion ("ProductName")

Linux programming: which device a file is in

I would like to know which entry under /dev a file is in. For example, if /dev/sdc1 is mounted under /media/disk, and I ask for /media/disk/foo.txt, I would like to get /dev/sdc as response.
Using stat system call on that file I will get its partition major and minor numbers (8 and 33, for sdc1). Now I need to get the "root" device (sdc) or its major/minor from that. Is there any syscall or library function I could use to link a partition to its main device? Or even better, to get that device directly from the file?
brw-rw---- 1 root floppy 8, 32 2011-04-01 20:00 /dev/sdc
brw-rw---- 1 root floppy 8, 33 2011-04-01 20:00 /dev/sdc1
Thanks in advance!
The quick and dirty version: df $file | awk 'NR == 2 {print $1}'.
Programmatically... well, there's a reason I started with the quick and dirty version. There's no portable way to programmatically get the list of mounted filesystems. (getmntent() gets fstab entries, which is not the same thing.) Moreover, you can't even parse the output of mount(8) reliably; on different Unixes, the mountpoint may be the first or the last item. The most portable way to do this ends up being... parsing df output (And even that is iffy, as you noticed with the partition number.). So you're right back to the quick and dirty shell solution anyway, unless you want to traverse /dev and look for block devices with matching major(st_rdev) (major() being from sys/types.h).
If you restrict this to Linux, you can use /proc/mounts to get the list of mounted filesystems. Other specific Unixes can similarly be optimized: for example, on OS X and I think FreeBSD, you can use sysctl() on the vfs tree to get mountpoints. At worst you can find and use the appropriate header file to decipher whatever the mount table file is (and yes, even that varies: on Solaris it's /etc/mnttab, on many other systems it's /etc/mtab, some systems put it in /var/run instead of /etc, and on many Linuxes it's either nonexistent or a symlink to /proc/mounts). And its format is different on pretty much every Unix-like OS.
The information you want exists in sysfs which exposes the linux device tree. This models the relationships between the devices on the system and since you are trying to determine a parent disk device from a partition, this is the place to look. I don't know if there are any hard and fast rules you can rely on to stop your code breaking with future versions of the kernel, but the kernel developers do try to maintain sysfs as a stable interface.
If you look at /sys/dev/block/<major>:<minor>, you'll see it is a symlink with the tail components being block/<disk-device-name>/<partition-device-name>. If you were to perform a readlink(2) system call on that, you could parse the link destination to get the disk device name. In shell (since it's easier to express this way, but doing it in C will be pretty easy):
$ echo $(basename $(dirname $(readlink /sys/dev/block/8:33)))
sdc
Alternatively, you could take advantage of the nesting of partition directories in the disk directories (again in shell, but from C, its an open(2), read(2), and close(2)):
$ cat /sys/dev/block/8:33/../dev
8:32
That assumes your starting major:minor is actually for a partition, not some other sort of non-nested device.
What you looking for is impossible - there is no 1:1 connection between a block device file and the partition it is describing.
Consider:
You can create multiple block device files with different names (but the same major and minor numbers) and they are indistinguishable (N:1)
You can use a block device file as an argument to mount to mount a partition and then delete the block device file leaving the partition mounted. (0:1)
So there is no way to do what you want except in a few specific and narrow cases.
Major number will tell you which device it is: 3 - IDE on 1st controller, 22 - IDE on 2nd controller and 8 for SCSI.
Minor number will tell you partition number and - for IDE devices - if it's primary or secondary drive. This calculation is different for IDE and SCSI.
For IDE it is: x*64 + p, x is drive number on the controller (0 or 1) and p is partition
For SCSI it is: y*16 + p, where y is drive number and p is partition
Not a syscall, but:
df -h /path/to/my/file
From https://unix.stackexchange.com/questions/128471/determine-what-device-a-directory-is-located-on
So you could look at df's source code and see what it does.
I realize this post is old, but this question was the 2nd result in my search and no one has mentioned df -h

Resources