A usage of setuid? - unix

I read a Powerpoint slide recently, and can't get a clear concept about the usage of setuid.
Here is the content of the slide.
Setuid example - printing a file
Goals
Every user can queue files
Users cannot delete other users' files
Solution
Queue directory owned by user printer
Setuid queue-file program
Create queue file as user printer
Copy joe's data as user joe
Also, setuid remove-file program
Allows removal only of files you queued
User printer mediated user joe's queue access.
Here are my questions.
I don't have a clear ​understanding​ how to solve this problem by "setuid".
First, if the file is created by user printer, how does user joe copy data to a file owned by printer. Does it have some certain right to this file.
Secondly, how to identify the relationship between you and the file you queued.
Does the file's state show something, but the file is owned by printer, which can only be changed by root. Does it have something to do with the file's gid? If so, other users' gid may also be related to this file.
Does the file's context show something about who queued it?
My questions are a mess, and I really don't have a clear concept about the solution.

Let's assume that the files are to be stored in /var/spool/pq directory; the permissions on the directory printer:printgrp:2700 (owner printer, group printgrp, mode 2700 - read, write, execute for owner only, and the SGID bit set on the directory means all files created in it will belong to group printgrp).
Further, we assume that the print queuing program, pq, has permissions printer:printgrp:4511 (setuid printer, anyone can execute it, but only printer or root can look at it).
Now, suppose Joe runs pq /home/joe/file, and the permissions on the file are joe:staff:600 (only Joe can read or write to the file). Joe's umask is set to 022 (though this file has more restrictive permissions than are implied by the umask).
When the program runs, the real UID of the process is joe, but the effective UID is printer. Since there is no need for setgid operation here, both the real and effective GID are staff. Joe's auxilliary groups list does not include printgrp.
Note that it is the effective UID and GID of a process that control its access to files. On his own, Joe cannot see what jobs are in the printer queue; the directory permissions shown don't even allow him to list the files, or access the files in the directory. Note that the converse applies; on its own, the printer user (or the pq program running as that user) cannot access Joe's file.
The pq program can create files in the printer queue directory; it will probably create two files for this request. One will be a control file, the other will be a copy of the file to be printed. It will determine a job number by some mechanism (say 12345) and it might create and open two files for writing (with restrictive permissions - 0600 or even 0400):
/var/spool/pq/c.12345 - the control file
/var/spool/pq/d.12345.1 - the first (only) data file
It should then reset its effective UID to the real UID, so it is running as Joe. It can then open the file Joe asked to be printed, and copy it to the data file. It can also write whatever information it deems relevant to the control file (date, time, who submitted the request, the number of files to be printed, special printing options, etc). When it closes those files, Joe is no longer able to access them. But the program was able to copy Joe's file to its print queue.
So, that addresses questions 1 (permissions) and 2 (control information), and also 4 (control information again).
Regarding question 3, root is always a wild card on Unix-like systems because can do anything that he wants. However, as suggested by the rest of the answer, the control file contains information about the print request, including (in particular) who submitted it. You can use setgid programs instead of setuid programs; these work in analogous ways. However, under the system I postulated, the group permissions essentially didn't come into the picture. The pq program set the permissions on the control file and data file such that the group can't read it, and the directory permissions also deny group access.
We can postulate two more programs:
pqs - printer queue status
pqr - printer queue remove
These programs would also be setuid printer. The pqs program can read the control files in the directory and list pertinent information from them. The pqr program can read the control files to ensure that when Joe submitted job 12345 when he requests the removal of job 12345. If the program is satisfied, then it can delete the files.
Separately from these user-invoked programs, there would also be a daemon program (conventionally named pqd in this system) that would be kicked into action by pq if it is not already running. It would be responsible for reading the control files in the directory, and using that information to actually print the data files to the relevant printer. The details of how different printers and different data formats are handled are a problem for the daemon to deal with. The daemon too will run with printer privileges, and printer will have been given access to the printer devices (for locally attached printers) or configured to communicate over the network with a protocol such as IPP (Internet Printer Protocol). Joe probably won't be able to use the printer devices directly.
Note that the setuid programs have powers that Joe does not have. They must be written carefully to ensure that Joe cannot abuse those extra powers. Any setuid program is somewhat dangerous; a setuid root program can be lethal. In general, setgid programs are less dangerous. However, for both types of program, great care is required in the writing of such programs.

Related

Is there anything like shm_open() without filename?

The POSIX shm_open() function returns a file descriptor that can be used to access shared memory. This is extremely convenient because one can use all the traditional mechanisms for controlling file descriptors to also control shared memory.
The only drawback is that shm_open() always wants a filename. So I need to do this:
// Open with a clever temp file name and hope for the best.
fd = shm_open(tempfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
// Immediately delete the temp file to keep the shm namespace clean.
shm_unlink(tempfilename);
// Then keep using fd -- the shm object remains as long as there are open fds.
This use of tempfilename is difficult to do portably and reliably. The interpretation of the filename (what the namespace is, how permissions are handled) differs among systems.
In many situations the processes using the shared memory object have no need for a filename because the object can be accessed more simply and safely by just passing a file descriptor from one process to another. So is there something that's just like shm_open() but can be used without touching the shared memory filename namespace?
mmap() with MAP_ANON|MAP_SHARED is great but instead of a file descriptor it gives a pointer. The pointer doesn't survive over an exec boundary and can't be sent to another process over a Unix domain socket like file descriptors can.
The file descriptor returned by shm_open() also doesn't survive an exec boundary by default: the POSIX definition says that the FD_CLOEXEC file descriptor flag associated with the new file descriptor is set. But it is possible to clear the flag using fcntl() on MacOS, Linux, FreeBSD, OpenBSD, NetBSD, DragonFlyBSD and possibly other operating systems.
A library to solve the problem
I managed to write a library that provides the simple interface:
int shm_open_anon(void);
The library compiles without warnings and successfully runs a test program on Linux, Solaris, MacOS, FreeBSD, OpenBSD, NetBSD, DragonFlyBSD and Haiku. You may be able to adapt it to other operating systems; please send a pull request if you do.
The library returns a file descriptor with the close-on-exec flag set. You can clear that flag using fcntl() on all supported operating systems, which will allow you to pass the fd over exec(). The test program demonstrates that this works.
Implementation techniques used in the library
The readme of the library has very precise notes on what was done and what wasn't done for each OS. Here's a summary of the main stuff.
There are several non-portable things that are more or less equivalent to shm_open() without a filename:
FreeBSD can take SHM_ANON as the pathname for shm_open() since 2008.
Linux has a memfd_create() system call since kernel version 3.17.
Earlier versions of Linux can use mkostemp(name, O_CLOEXEC | O_TMPFILE) where name is something like /dev/shm/XXXXXX. Note that we are not using shm_open() at all here -- mkostemp() is implicitly using a perfectly ordinary open() call. Linux mounts a special memory-backed file system in /dev/shm but some distros use /run/shm instead so there are pitfalls here. And you still have to shm_unlink() the temp file.
OpenBSD has a shm_mkstemp() call since release 5.4. You still have to shm_unlink() the temp file but at least it is easy to create safely.
For other OSes, I did the following:
Figure out an OS-dependent format for the name argument of POSIX shm_open(). Please note that there is no name you can pass that is absolutely portable. For example, NetBSD and DragonFlyBSD have conflicting demands about slashes in the name. This applies even if your goal is to use a named shm object (for which the POSIX API was designed) instead of an anonymous one (as we are doing here).
Append some random letters and numbers to the name (by reading from /dev/random). This is basically what mktemp() does, except we don't check whether our random name exists in the file system. The interpretation of the name argument varies wildly so there's no reasonable way to portably map it to an actual filename. Also Solaris doesn't always provide mktemp(). For all practical purposes, the randomness we put in will ensure a unique name for the fraction of a second that we need it.
Open the shm object with that name via shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600). In the astronomical chance that our random filename already exists, O_EXCL will cause this call to fail anyway, so no harm done. The 0600 permissions (owner read-write) are necessary on some systems instead of blank 0 permissions.
Immediately call shm_unlink() to get rid of the random name. The file descriptor remains for our use.
This technique is not quaranteed to work by POSIX, but:
The shm_open() name argument is underspecified by POSIX so nothing else is guaranteed to work either.
I'll let the above compatibility list speak for itself.
Enjoy.
No, there isn't. Since both System V shared memory model and POSIX shared file mapping for IPC require operations with a file, there is always need for a file in order to do mapping.
mmap() with MAP_ANON|MAP_SHARED is great but instead of a file
descriptor it gives a pointer. The pointer doesn't survive over an
exec boundary and can't be sent to another process over a Unix domain
socket like file descriptors can.
As John Bollinger says,
Neither memory mappings created via mmap() nor POSIX shared-memory
segments obtained via shm_open() nor System V shared-memory segments
obtained via shmat() are preserved across an exec.
There must be a well-known place on the memory to meet and exchange information. That's why a file is the requirement. By doing this, after exec, the child is able to reconnect to the appropriate shared memory.
This use of tempfilename is difficult to do portably and reliably. The interpretation of the filename (what the namespace is, how permissions are handled) differs among systems.
You can have mkstemp create a unique filename in /dev/shm/ or /tmp and open the file for you. You can then unlink the filename, so that no other process can open this file, apart from the process that have the file descriptor returned from mkstemp.
mkstemp(): CONFORMING TO 4.3BSD, POSIX.1-2001.
Why not creating it with access rights to 0?
Thus no process would be able to "open" it and let you unlink it safely just after?

What would be the best practice downloading all the files from a directory using Sftp

I would like to implement the following functionality:
downloading all the files from a specified remote directory to a local directory.
after downloading all the files I need a list file which contains all the downloaded files.
(I only want this list file when all the files were downloaded successfully.)
Point 1:
Let's say we have around 10 files in the remote directory.
I can use an int-sftp:inbound-channel-adapter component to download all the files but 10 poll cycles are needed to download all of them since the inbound component is only able to download 1 file per poll request.
Spring Integration creates 10 File messages one by one.
Questions:
How can I identify the last file (message) received from the FTP server?
I don't want let users access to list file till all the files from the FTP is successfully received.
How can I achive this?
I can write file names into a list file using the int-file:outbound-channel-adapter but users can read temorary information from that file before the download process is finished.
How can I trigger the event that all files which are on the FTP are downloaded?
Thanks for your advices
Ferenc
First of all this isn't correct:
the inbound component is only able to download 1 file per poll request
You can configure it to to download infinitely during the single poll - max-messages-per-poll=-1. Anyway it is a default option on <poller>.
Anyway if it is your case to dowload one file per poll, you can go ahead with that requirements.
Since any Messaging system tries to achieve stateless paradigm, it is normal that one message doesn't know anything about another. And with that they all don't impact each other. The async scenario is the best for Messaging. With that we can process the second message quicker, than the first one.
Your requirement is enough interest and I won't dare to call it strange. Because any business may have place.
Since you are going to process several download files as one group, there will be need to have some marker on the remote server. Or it can be some timeframe, which we can extract from file timestamp. Or there will be need to store on the remote server some marker file to point that a set of files are finished and you can process them from your application using their local version. Would be great, if that marker file can contain a list of file names of that group.
Otherwise we don't have any hook to group messages for those files.
From other side you can consider to use <int-sftp:outbound-gateway> with MGET command: http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/sftp.html#sftp-outbound-gateway

How to configure Oracle 11g to launch sqlplus?

On a RedHat 6 server, a third party application requires to be root to run and needs access to sqlplus. I have a running database, I can run sqlplus as user 'oracle'. When logged in as user root, 'sqlplus usr/pwd#dbname' works as expected. The trouble is that this agent needs to run sqlplus with no parameters and it always returns ORA-12546: TNS:permission denied.
I've read a dozen times that enabling root to launch Oracle is a security issue but I really have no other choice.
Running Oracle 11.2.0.1.0.
Any help will be much appreciated as I've googled for 2 days with no success.
From the documentation, ORA_12546 is:
ORA-12546: TNS:permission denied
Cause: User has insufficient privileges to perform the requested operation.
Action: Acquire necessary privileges and try again.
Which isn't entirely helpful, but various forum and blog posts (way too many to link to, Googling for the error shows a lot of similar advice) mention permissions on a particular part of the installation, $ORACLE_HOME/bin/oracle, which is a crucial and central part of most of the services.
Normally the permissions on that file would be -rws-r-s--x, with the file owned by oracle:dba, and this error can occur when the word-writable flag - the final x in that pattern - is not set. Anyone in the dba group will still be able to execute it, but those outside will not.
Your listener seems to be fine as you can connect remotely, by specifying #dbname in the connect string. The listener runs as oracle (usually, could be grid with HA, RAC or ASM) so it is in the dba group and can happily hand-off connections to an instance of the oracle executable.
When you connect without going via the listener, you have to be able to execute that file yourself. It appears that root cannot execute it (or possibly some other file, but this is usually the culprit, apparently), which implies the world-writable bit is indeed not set.
As far as I can see you have three options:
set the world-writable bit, with chmod o+x $ORACLE_HOME/bin/oracle; but that opens up the permissions for everyone, and presumably they've been restricted for a reason;
add root to the dba group, via usermod or in the /etc/group; which potentially weakens security as well;
use SQL*Net even when you don't specify #dbname in the connect string, by adding export TWO_TASK=dbname to the root environment.
You said you don't have this problem on another server, and that the file permissions are the same; in which case root might be in the dba group on that box. But I think the third option seems the simplest and safest. There is a fourth option I suppose, to install a separate instant client, but you'd have to set TWO_TASK anyway and go over SQL*Net, and you've already ruled that out.
I won't dwell on whether it's a good idea to run sqlplus (or indeed the application that needs it) as root, but will just mention that you'd could potentially have a script or function called sqlplus that switches to a less privileged account via su to run the real executable, and that might be transparent to the application. Unless you switch to the oracle account though, which is also not a good idea, you'd have the same permission issue and options.

CODA setting owner & group [duplicate]

I have a script (Joomla) that creates files and directories on the server. The problem is that it creates them under owner 99 99 (nobody) and after I can't delete or modify them by FTP without the help of the server admin.
I think that is move_uploaded_file function of php.
Is there any solution of this problem by the WHM or by the server admin? Can I modify the default owner in ftp?
What happens is the HTTP server is ran by a user called "nobody", and your FTP user is another one. When the upload occurs, the HTTP server creates the file under its username, and your FTP user has no permission to write (or delete) these files.
The easiest way to fix this (but not really secure) is to add both users in a same group, and change the file permissions to allow users of the same group to read/write on these files.
Your admin should take care of it, but you'll have to call chmod() to change the permissions of your uploaded files.
Explaining it better:
The linux/unix file permissions are composed by permissions of user (u), group (g) and others (o).
I'll only cover 3 types of file permisions here, which are read (r), write (w) and execute (x). So, you end up having something like this:
-rw-rw---x 1 jweyrich staff 12288 Oct 24 00:22 avatar.png
The first rw- is the permission (read/write) of the USER that owns the file (jweyrich).
The second rw- is the permission (read/write) of the GROUP that owns the file (staff).
The --x at the end are the permissions (execute) of the OTHERS users..
Your PHP scripts run as "nobody" user (and by, let's say, "nobody" group), so every file you create from your PHP will be owned by the "nobody" user (and his group). A user can be part of one or more groups.
To solve the permission problem, your FTP user and the "nobody" must be in a common group, let's say the admin put your user in the "nobody".
Once they're in the same group, your PHP script has to give "rw" (read/write) permissions to the "nobody" group members. To do so:
chmod("path_to_your_file", 0770);
The 0770 is equivalent to "u+rwx,g+rwx,o-rwx" , which I explain here:
u+rwx = for user (owner, which is "nobody"), give read/write/execute permissions
u+rwx = for group (which is also "nobody"), give read/write/execute permissions
o-rxw = for others, remove the read/write/execute permissions
After that, your FTP user, which is now part of the "nobody" group, will have read//write access to the uploaded files, and thus can also delete the files. It would look like this:
-rwxrwx--- 1 nobody nobody 12288 Oct 24 00:22 avatar.png
It's not the ideal introduction to unix file permissions, but I hope this helps.
The user that PHP runs under - nobody - is set by the system administrator. There's nothing you can do about that.
You can try chown() to change the file's owner if you know the FTP user's ID. Usually though, you will not be allowed to do this from within PHP.
Depending on the group situation on the server, it could be that if you use chmod to change the file's access rights after the file has been uploaded, the FTP account can access the file:
Try this first:
chmod($uploaded_file, 0660); // owner+group read+write
If that doesn't work, try this:
chmod($uploaded_file, 0666); // global read+write
one of these should make the file usable by the FTP account.
The 0666 is highly discouraged because other users on the server could write into your files, but in some configurations, it's the only way to get going.

What are the well-known UIDs?

According to the useradd manpage, UIDs below 1000 are typically reserved for system accounts.
I'm developing a service that will run as its own user. I know that well-known ports can be found in /etc/services.
Is there a place where I can find out what well-known UIDs are out there? I would like to avoid crashing with someone else's UID.
getpwent(3) iterates through the password database (usually /etc/passwd, but not necessarily; for example, the system may be in a NIS domain). Any UID known to the system should be represented there.
For demonstration, the following shell fragment and C code both should print all known UIDs on the system.
$ getent passwd | cut -d: -f3
#include <pwd.h>
#include <stdio.h>
int main() {
struct passwd *pw;
while ((pw = getpwent()))
printf("%d\n", pw->pw_uid);
}
UID 0 is always root and conventionally UID 65534 is nobody, but you shouldn't count on that, nor anything else. What UIDs are in use varies by OS, distribution, and even system -- for example, many system services on Gentoo allocate UIDs as they are installed. There is no central database of UIDs in use.
Also, /etc/login.defs defines what "system UIDs" are. On my desktop, it is configured so that UIDs 100-999 are treated as system accounts, and UIDS 1000-60000 are user accounts, but this can easily be changed.
If you are writing a service, I would suggest that the package installation be scripted to allocate a UID as needed, and that your software be configurable to use any UID/username.
I know this is an old post, but since I am here in 2017, still trying to answer a similar question I thought this additional information was relevant for anyone else in the same position.
The concept of "Well known UIDs" stems back to the early days of unix, before there were multitudes of distributions and unix variants. "Well known" UIDs were considered to be those for system users like adm, daemon, lp, sync, operator, news, mail etc, and were standard across all the various systems in order to avoid uid clashes. These users are still present in modern unix-like operating systems.
Standardising uid's across an organisation is the key to avoiding these problems. As was pointed out in a comment above, these days any uid you choose is likely to be in use 'somewhere', so the best a sysadmin can aim for is to ensure that uid's are standard across all the systems that they maintain, then allocating a new uid for an application becomes simple.
To that end, for many years I have found the post linked below invaluable, and sadly there are not a lot of similar posts on the topic, and what's out there is hard to find.
UNIX/Linux: Analyzing user/group UID/GID conflicts
If you search that blog under the 'uid' tag there are other relevant posts, including a script to automate the process of standardising uid's across multiple hosts under Linux.
This User ID Definition is also an invaluable resource.
The short answer is, that it doesn't really matter which uid's you use, as long as they are unique and standard across your organisation, to avoid clashes.
I'm not sure such a list exists. How about just noting that UID's are in use through the /etc/passwd file, /etc/shadow file, and the NIS global user list, noting what ones are in use? Then use one that isn't!
In Linux, that is configured in /etc/login.defs. Sometimes, when I install a Debian-based system, I change the "uid start" option (I forget its name, I'm not on Linux now) from 1000 to 500 for consistency with the other, Red Hat-y machines.
man login.defs should give you all the info you want.

Resources