libaps-general Mailing List for Application Print Services Library (Page 2)
Brought to you by:
brianpirie,
tranter
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
(16) |
May
(2) |
Jun
(12) |
Jul
(3) |
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
(1) |
---|
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:44
|
From: "Jeff Brown" <jef...@co...> Subject: The dangers of using sprintf(). Date: Tuesday, February 08, 2000 6:08 pm Hello everyone, I'm sure you're all aware of the problems surrounding the use of such functions as sprintf(), strcpy(), strcat() etc... For the longest time I was wondering why there did not seem to be a variant of sprintf() which dynamically allocated the buffer it needed or which could accept a maximum size. Apparently, I was wrong... I would like to direct your attention to asprintf() and snprintf() which perform the above tasks splendidly. If portability issues arise, it is fairly trivial to provide safe / safer frontends to sprintf() conforming to the above definition. I would suggest doing a grep on your source files and look at ways of avoiding the use of sprintf() with fixed-length buffers. If it's possible to compute the total length beforehand and the string is local to a function, use alloca() to create the buffer. alloca() is fast, almost guaranteed to succeed, and needn't be free'd() as the buffer gets popped off the stack when the stack unwinds because of the function returning or some exception. From: "Brian Pirie" <br...@co...> Subject: Re: The dangers of using sprintf(). Date: Wednesday, February 09, 2000 10:33 am asprintf() and snprintf() are wonderful functions! In my opinion, it is a real shortcoming of the ANSI C standard that these (and other functions, such as strdup()) aren't included. You're right that if we want to do something like this, we need to be very careful of portability. In the front-end functions you're suggesting, if we're building on a plain-ANSI C compiler that lacks asprintf() or snprintf(), how would we determine how long the string is going to be without essentially implementing a complete printf-format parser, that looks at each % field to determine how long the buffer needs to be? There are places in the code where we're using sprintf() or atoi(), where we are careful that the destination buffers are appropriately sized for the largest data that we can have. Because, as you point out, this is really dangerous, at the very least we should have ASSERTs() to test for any assumptions we're making about maximum sizes. Do you have any other ideas for things that we can do to reduce the danger in these sorts of situations? Brian From: "Jeff Brown" <jef...@co...> Subject: Re: The dangers of using sprintf(). Date: Wednesday, February 09, 2000 12:57 pm > You're right that if we want to do something like this, we need to be very > careful of portability. In the front-end functions you're suggesting, if we're > building on a plain-ANSI C compiler that lacks asprintf() or snprintf(), how > would we determine how long the string is going to be without essentially > implementing a complete printf-format parser, that looks at each % field to > determine how long the buffer needs to be? There is little other choice. Thankfully, printf is not something very complex. However we're overlooking something here. Portable implementations of these functions must exist already in OpenSource. We would then need only place those modules in the contrib/ folder or similar. If it comes to writing a new printf()-like formatter, all I can say is that it's actually much easier than it looks. *smile* > There are places in the code where we're using sprintf() or atoi(), where we are > careful that the destination buffers are appropriately sized for the largest > data that we can have. Because, as you point out, this is really dangerous, at > the very least we should have ASSERTs() to test for any assumptions we're making > about maximum sizes. As you pointed out, there is no way of building ASSERTs for such conditions short of writing a printf-style parser. > Do you have any other ideas for things that we can do to reduce the danger in > these sorts of situations? Build strings atomically using strncpy() and strncat() where appropriate. Or, as I suggested, try to precompute the length of the string beforehand and make a call to alloca() to allocate your buffer for you. If you're dead-set on using static buffers, insert field width qualifiers into the sprintf() format string. eg. "%20s %5d". Jeff Brown. (x5625) From: "Brian Pirie" <br...@co...> Subject: Re: The dangers of using sprintf(). Date: Wednesday, February 09, 2000 3:21 pm > complex. However we're overlooking something here. Portable > implementations of these functions must exist already in OpenSource. We > would then need only place those modules in the contrib/ folder or similar. Unfortunately, unless they're released under the LGPL license, we can't use them. Even GPLed code would be off-limits. > > data that we can have. Because, as you point out, this is really > dangerous, at > > the very least we should have ASSERTs() to test for any assumptions we're > making > > about maximum sizes. > > As you pointed out, there is no way of building ASSERTs for such conditions > short of writing a printf-style parser. What I had in mind is if you had a piece of code that did something like: char dest[5]; sprintf(dest, "%d", value); This code is assuming that value will never be more than 4 digits. So, you could do an: ASSERT(value < 10000 && value > -1000); To make it immediately obvious if that assumption was ever violated. Brian From: "Jeff Brown" <jef...@co...> Subject: Re: The dangers of using sprintf(). Date: Wednesday, February 09, 2000 4:47 pm > What I had in mind is if you had a piece of code that did something like: > > char dest[5]; > sprintf(dest, "%d", value); > This code is assuming that value will never be more than 4 digits. So, you could > do an: > > ASSERT(value < 10000 && value > -1000); ICK! There must be a better way, but I see your point. There's no reason a programming language couldn't hide these internals from view, geez... If the above construction were to be used in many places, I would consider writing a macro or inline'd function for handling the circumstance. |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:44
|
From: "Jeff Brown" <jef...@co...> Subject: Remote printers Date: Monday, February 28, 2000 6:12 pm Hello everyone, This will be short and sweet. I was scanning the APS source to determine *exactly* what happened when a printer was added to the system using Aps_AddPrinter -- paying particular attention to the handling of remote printers. In the LPR support, it appears that the manner in which Aps_Printer[Get/Set]ConnectInfo are supported fails to distinguish between the various queues of a remote printer. Specifically, this information is either not specified when calling the API function, or is not parsed into its component 'hostname' / 'queue' pair. Clearly this kind of identification must be supported or network printer support -- particularly NCP / Unix / LPD printers will be broken. I'm essentially calling for a common naming convention for remote network printer locations. Presently they are represented using transport-/network-specific tags/paths making it difficult for an app to find out just "where" in the network a given device is located. It needn't be anything extravagant. In fact, the following URL format would be wholly sufficient: <protocol>://<hostname or ip>:<port #>/<queuename> Printer groups / subqueues can be represented using common directory naming schemes: <protocol>://<host>:<port>/<group>/<queue>, etc... eg. smb://myhost/myprinter, ncp://myhost:myport/myprinter, foobar://myhost:myport/myworkgroup/myqueue Conversion between proprietary formats could also be provided via suitable functions. eg. Aps_ConvertNetworkPath( enum NetworkType dest, char *destpath, int bufsize, enum NetworkType src, const char *srcpath); In this way an application can choose to represent a path either in native format, or parse it to provide some form of hierarchial breakdown. Jeff. |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:43
|
From: "Jeff Brown" <jef...@co...> Subject: Proposed extensions for improved job control Date: Monday, February 07, 2000 8:26 pm Recent improvements to APS now allow it to store substantially more information with jobs than ever before. Specifically, this means that it is now possible to tag jobs with summary document information. Presumably APS could generate improved header sheets (aka. burst pages) for printing in office environments. APS also stores a small amount of routing information to assist in networked environments. The problem is that APS currently fails to provide support for any of the following. [some fields have been reserved, and some are even managed internally but cannot be set by the application] - dispatching multiple files as a single job - printing multiple copies of the same job - tagging jobs with a name, title, comments, author, etc... - classifying jobs into groups (LPRng permits the grouping of jobs into classes which can be paused / resumed on an individual basis) As an example of the kind of information which can be tagged along with jobs, consider Wordperfect's document information. It is feasible for WP to export the document's author, title, revision label, and comments for use by the printing process. This info could then appear in queue display interfaces, on header sheets, or in log files as part of a document tracking / auditing system. Printing multiple copies or multiple files as a single job is fairly trivial and worth looking into... At the very least, it means my little Berkeley LPR - alike frontends for APS will be able to better mimic the function of the programs they replace. Jeff Brown. (x5625) From: "Swapan Jain" <sw...@co...> Subject: Re: Proposed extensions for improved job control Date: Tuesday, February 08, 2000 10:58 am Hi Jeff, I appreciate your proposal. Sending of multiple files as a single job should not be much difficult. We can merge all the files and send it as a single job. We can modify Aps_JobWrite function(may be it will be renamed as Aps_JobsWrite then) for this purpose. What do you think.? Swapan From: "Jeff Brown" <jef...@co...> Subject: Re: Proposed extensions for improved job control Date: Tuesday, February 08, 2000 6:10 pm Swapan, > Sending of multiple files as a single job should not be much difficult. We can > merge all the files and send it as a single job. We can modify Aps_JobWrite > function(may be it will be renamed as Aps_JobsWrite then) for this purpose. > > What do you think.? Hmmm... As I see it, we'd have to distinguish the opening of a Job object from the contents placed within. A simple approach for this is to provide an Aps_JobNewSegment() / Aps_JobEndSegment() pair of operations which essentilly break a job into multiple parts or files. Using Aps_JobWriteFile() in a new segment could then handle the multiple file problem. Another advantage of segments is that they could help us track progress more easily. eg. Create a new segment for each page... Merging files is inadequate as the transport may wish to do things in between each file, like insert form feeds, initialization code, send an email to the user, or popup a dialog box. I'm looking to create a generic abstraction of LPR's ability to send multiple files to be printed sequentially, as a single job. Right now when the queue reading code encounters a job with multiple files, it concatenates their names, and filenames using the pipe character '|' as a delimiter. This behaviour is provided as a stopgap measure. If support for multiple segments is provided, then each segment would get its own [local filename], [spool filename], [size] tuple. Jeff. |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:42
|
From: "Jeff Brown" <jef...@co...> Subject: Ensuring consistent application of file permissions and ownership Date: Friday, March 10, 2000 1:17 pm Hello everyone, This week we ran into a number of issues which were related to the improper application of file permissions and ownership. In particular, these showed up because of the "unusual" environment of a setuid binary. In such a program, it is *very* important to ensure that we use the *right* user id and group id before creating administrative or even temporary files. The problem itself is fairly straightforward, but the existing solutions are messy. 1. All normal admin files should be created as follows: - owner : default administrator (usu. root) - group : default administrative group (usu. root) - permissions: u+rw g+rw o+r Managing the group setting allows us to create more complex administrative systems where perhaps a priviledged group has access to config files, not just root. We should be DISCOURAGING the need for a super-user as much as possible. 2. Anything that has to be associated with the owner should be created as follows: - owner : as returned by getuid() - group : as returned by getgid() - permissions: u+rw g+r o+r 3. Private admin files should be created as #1 with perms: u+rw g+rw only. 4. Private user files should be created as #2 with perms: u+rw only. Note it is NOT safe to assume that #2 will be followed. Specifically, this assumption fails in a setuid binary. The default is for files to be created using the euid and egid. In such programs, the following may be true: euid != uid and/or egid != gid. There are other cases where this may occur. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Proposal: ========= Centralize all file creation / updating / manipulation operations to a single module. The advantages are clear. First, we reduce the overall code size and redundancy. Second, it makes the program far easier to port. Third, by adopting certain internal standards, it would be possible to adapt APS to conform to just about any security environment. Fourth, the module could be reused by other Corel / OpenSource applications. Specific proposed design criteria: ================================== 1. A means for specifying file access modes: - whether file should be opened for reading - whether file should be opened for writing - whether file should be seekable (excludes some pipes / sockets) - whether a C-stdio file pointer will be used 2. A means for specifying handling of existing files: - create if not found, else fail - discard existing file - append to existing file - replace safely - avoid collisions - create backup of existing file 3. A means of handling safe replacement of existing files with facilities for reversing / aborting operations: - Possible implementation: rename file to unique backup create new file in its place on close, discard original file on abort, restore original file <Problem : susceptible to race condition between move and creation> <Benefits : easy to implement> - Possible implementation: create temporary file on close, rename original file out of the way rename new file to old position discard original file on abort, discard temporary file <Problem : susceptible to race consitions between moves> <Benefits : requires minimal recovery code> - Possible implementation: lock original file / open for r/w without destroying create temporary file on close, copy contents over original file using open descriptor on abort, do nothing discard temporary file <Problem : may block access to original file / this may be desirable> <Benefits : ensures file is always in a consistent state> 4. A means of specifying permissions and ownership when writing files - public administrative file: assume permissions u+rw, g+rw, o+r explicitely specify administrative owner / group (default root) - private administrative file: assume permissions u+rw, g+rw, o none explicitely specify administrative owner / group (default root) - public user file: assume permissions u+rw, g+r, o+r assume ownership: group = getgid(), owner = getuid() - private user file: assume permissions u+rw, g none, o none assume ownership: group = getgid(), owner = getuid() - private group-visible user file: assume permissions u+rw, g+r, o none assume ownership: group = getgid(), owner = getuid() - public group file: assume permissions u+rw, g+rw, o+r assume ownership: group = getgid(), owner = getuid() - private group file: assume permissions u+rw, g+rw, o none assume ownership: group = getgid(), owner = getuid() - any of above plus executable bit for all with read access - any of above plus executable setuid and/or setgid bits - explicit specification of all settings 5. A means of manipulating directories using similar procedures, specifically - specify directory visibility and access rights - specify "sticky" bit - apply simple safe-creation concepts to directories - apply handling of existing file notions to directories (eg. discard existing directory) 6. A means of tracking all of this information as a package - package information about open files into a structure / other object - package file/dir open settings into a structure / other object 7. A means of ensuring that the created objects are threadsafe - assume libc6 i/o is threadsafe - avoid global structures - avoid race conditions - if atomic operations are not available, use a semaphore or other control mechanism to avoid potential problems - allow such a mechanism to be supplied by the user (or ./configure script) using #define macros or abstract / virtual interface - provide a #if PARANOID interface to wrap all calls to library functions 8. A comprehensive error control mechanism - do not use Aps_Result (avoid dependancy on APS constructions to improve modularity) - privide #if blocks to export errors in the "errno" variable so that the implementation can be used as a "drop-in replacement" to the highest possible degree - return a very limited set of enumerated constants only for common conditions 9. A means of recompiling the interface for direct use in a C++ environment - use #ifdef __CPLUSPLUS blocks to hide all C++ details from C - for C++, use extern "C" { } in header file around prototypes - for C++, provide compile-time option to throw exceptions on errors (easily done if error control is centralized) - (optional) provide ifstream / ofstream wrapper Interface characteristics: ========================== Supported operations: - file open - file close & commit - file close & abort - file get properties (about its opened state) - file set permissions / ownership (w/o opening) - directory synchronous creation - directory deferred creation - directory deferred creation commit - directory deferred creation abort - directory get properties (about its deferred state) - directory set permissions / ownership (w/o creating) - create file inside directory with deferred creation - (optional) link set of opened files / deferred directories into a single descriptor with "commit all" and "abort all" operations History: ======== At the moment similar operations are being applied to files in lprprefs.c. Jeff Brown. (x5625) From: "Jeff Brown" <jef...@co...> Subject: Re: Ensuring consistent application of file permissions and ownership Date: Friday, March 10, 2000 2:20 pm Further to the previous message, I'd like to make the following observations: 1. DO NOT use the access() function to determine if the user has access if you really mean to see if the file can be opened. There are two problems with this mechanism: a. Assumptions of this type are open to race conditions and should not form the base of any "safe overwriting" mechanism. b. The REAL uid / gid pair is used instead of the EFFECTIVE uid / gid pair. access() may report a file is inaccessible even if it the filesystem would have permitted it based on euid / egid. 2. DO NOT perform explicit comparisons of euid / egid to guage root access. If you're really interested in determining if a user has administrative access and performing authentication based on that, then perform one of the following tasks: a. Define variables specifying the default administrative user and default administrative group. These could be root. Now test if the ((uid == uidAdmin) || (uid belongs to gidAdmin)). The second test does not simply mean (gid == gidAdmin). If the test succeeds, set euid = uidAdmin, egid = gidAdmin. If not, perform authentication and test if the authenticated ((euid == uidAdmin) || (euid belongs to gidAdmin)). If so leave euid alone and set egid to gidAdmin. b. If ((euid == uid) && (egid == gid)) use access(..., W_OK) on a known-good administrative file. If this fails, then request authentication as above. Now test if the file is accessible by this euid / egid by using stat() or open(). If this succeeds, you now have administrative access. 3. The following functions have write operations with potential race conditions or improper permissions: MetaOpenForWrite() Aps_AddModelFromPPD() PPDCreateCustomPPD() 4. APS should perform comprehensive authentication of access only in the high-level calls. (eg. Aps_AddPrinter, Aps_PrinterSetModel, ...) It should then ensure that the euid / egid are set to "sane" values and real uid / gid reflect the true identity of the user logged in. Low-level functions and operations involving the creation of files or manipulation of administrative settings should assume that admin files are to be created using the current euid / egid (ie. not explicitely select root to be the recipient of ownership), and use the current real uid / gid when we are interested in the user's true identity. (Like when we tag the id with a job, or store information in a log). 5. APS should not deal with passwords / switching users at all! Let the app do this as it (supposedly) knows best what is needed for each situation. To simplify things for the app, we may offer a global service for setting default admin uid / gid for functions which require it. We would then ensure that euid / egid are set to these values and restored appropriately for each administrative function unless one or both of the values in the uid/gid pair are -1. void Aps_SetDefaultAdmin( uid_t uid, gid_t gid); Aps_SetDefaultAdmin( 0, 0); /* selects root */ Aps_SetDefaultAdmin( -1, -1); /* selects "nobody", disables */ Aps_SetDefaultAdmin( -1, group); /* don't touch user */ I think this would greatly simplify the creation of administrative programs like kcmprint. It would also be possible to have APS store a "GLOBAL DEFAULT" in privileged configuration files or to request them from a secure server. Ideas??? RFC. Jeff Brown. (x5625) |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:42
|
From: "Jeff Brown" <jef...@co...> Subject: Ensuring consistent application of file permissions and ownership Date: Friday, March 10, 2000 1:17 pm Hello everyone, This week we ran into a number of issues which were related to the improper application of file permissions and ownership. In particular, these showed up because of the "unusual" environment of a setuid binary. In such a program, it is *very* important to ensure that we use the *right* user id and group id before creating administrative or even temporary files. The problem itself is fairly straightforward, but the existing solutions are messy. 1. All normal admin files should be created as follows: - owner : default administrator (usu. root) - group : default administrative group (usu. root) - permissions: u+rw g+rw o+r Managing the group setting allows us to create more complex administrative systems where perhaps a priviledged group has access to config files, not just root. We should be DISCOURAGING the need for a super-user as much as possible. 2. Anything that has to be associated with the owner should be created as follows: - owner : as returned by getuid() - group : as returned by getgid() - permissions: u+rw g+r o+r 3. Private admin files should be created as #1 with perms: u+rw g+rw only. 4. Private user files should be created as #2 with perms: u+rw only. Note it is NOT safe to assume that #2 will be followed. Specifically, this assumption fails in a setuid binary. The default is for files to be created using the euid and egid. In such programs, the following may be true: euid != uid and/or egid != gid. There are other cases where this may occur. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Proposal: ========= Centralize all file creation / updating / manipulation operations to a single module. The advantages are clear. First, we reduce the overall code size and redundancy. Second, it makes the program far easier to port. Third, by adopting certain internal standards, it would be possible to adapt APS to conform to just about any security environment. Fourth, the module could be reused by other Corel / OpenSource applications. Specific proposed design criteria: ================================== 1. A means for specifying file access modes: - whether file should be opened for reading - whether file should be opened for writing - whether file should be seekable (excludes some pipes / sockets) - whether a C-stdio file pointer will be used 2. A means for specifying handling of existing files: - create if not found, else fail - discard existing file - append to existing file - replace safely - avoid collisions - create backup of existing file 3. A means of handling safe replacement of existing files with facilities for reversing / aborting operations: - Possible implementation: rename file to unique backup create new file in its place on close, discard original file on abort, restore original file <Problem : susceptible to race condition between move and creation> <Benefits : easy to implement> - Possible implementation: create temporary file on close, rename original file out of the way rename new file to old position discard original file on abort, discard temporary file <Problem : susceptible to race consitions between moves> <Benefits : requires minimal recovery code> - Possible implementation: lock original file / open for r/w without destroying create temporary file on close, copy contents over original file using open descriptor on abort, do nothing discard temporary file <Problem : may block access to original file / this may be desirable> <Benefits : ensures file is always in a consistent state> 4. A means of specifying permissions and ownership when writing files - public administrative file: assume permissions u+rw, g+rw, o+r explicitely specify administrative owner / group (default root) - private administrative file: assume permissions u+rw, g+rw, o none explicitely specify administrative owner / group (default root) - public user file: assume permissions u+rw, g+r, o+r assume ownership: group = getgid(), owner = getuid() - private user file: assume permissions u+rw, g none, o none assume ownership: group = getgid(), owner = getuid() - private group-visible user file: assume permissions u+rw, g+r, o none assume ownership: group = getgid(), owner = getuid() - public group file: assume permissions u+rw, g+rw, o+r assume ownership: group = getgid(), owner = getuid() - private group file: assume permissions u+rw, g+rw, o none assume ownership: group = getgid(), owner = getuid() - any of above plus executable bit for all with read access - any of above plus executable setuid and/or setgid bits - explicit specification of all settings 5. A means of manipulating directories using similar procedures, specifically - specify directory visibility and access rights - specify "sticky" bit - apply simple safe-creation concepts to directories - apply handling of existing file notions to directories (eg. discard existing directory) 6. A means of tracking all of this information as a package - package information about open files into a structure / other object - package file/dir open settings into a structure / other object 7. A means of ensuring that the created objects are threadsafe - assume libc6 i/o is threadsafe - avoid global structures - avoid race conditions - if atomic operations are not available, use a semaphore or other control mechanism to avoid potential problems - allow such a mechanism to be supplied by the user (or ./configure script) using #define macros or abstract / virtual interface - provide a #if PARANOID interface to wrap all calls to library functions 8. A comprehensive error control mechanism - do not use Aps_Result (avoid dependancy on APS constructions to improve modularity) - privide #if blocks to export errors in the "errno" variable so that the implementation can be used as a "drop-in replacement" to the highest possible degree - return a very limited set of enumerated constants only for common conditions 9. A means of recompiling the interface for direct use in a C++ environment - use #ifdef __CPLUSPLUS blocks to hide all C++ details from C - for C++, use extern "C" { } in header file around prototypes - for C++, provide compile-time option to throw exceptions on errors (easily done if error control is centralized) - (optional) provide ifstream / ofstream wrapper Interface characteristics: ========================== Supported operations: - file open - file close & commit - file close & abort - file get properties (about its opened state) - file set permissions / ownership (w/o opening) - directory synchronous creation - directory deferred creation - directory deferred creation commit - directory deferred creation abort - directory get properties (about its deferred state) - directory set permissions / ownership (w/o creating) - create file inside directory with deferred creation - (optional) link set of opened files / deferred directories into a single descriptor with "commit all" and "abort all" operations History: ======== At the moment similar operations are being applied to files in lprprefs.c. Jeff Brown. (x5625) From: "Jeff Brown" <jef...@co...> Subject: Re: Ensuring consistent application of file permissions and ownership Date: Friday, March 10, 2000 2:20 pm Further to the previous message, I'd like to make the following observations: 1. DO NOT use the access() function to determine if the user has access if you really mean to see if the file can be opened. There are two problems with this mechanism: a. Assumptions of this type are open to race conditions and should not form the base of any "safe overwriting" mechanism. b. The REAL uid / gid pair is used instead of the EFFECTIVE uid / gid pair. access() may report a file is inaccessible even if it the filesystem would have permitted it based on euid / egid. 2. DO NOT perform explicit comparisons of euid / egid to guage root access. If you're really interested in determining if a user has administrative access and performing authentication based on that, then perform one of the following tasks: a. Define variables specifying the default administrative user and default administrative group. These could be root. Now test if the ((uid == uidAdmin) || (uid belongs to gidAdmin)). The second test does not simply mean (gid == gidAdmin). If the test succeeds, set euid = uidAdmin, egid = gidAdmin. If not, perform authentication and test if the authenticated ((euid == uidAdmin) || (euid belongs to gidAdmin)). If so leave euid alone and set egid to gidAdmin. b. If ((euid == uid) && (egid == gid)) use access(..., W_OK) on a known-good administrative file. If this fails, then request authentication as above. Now test if the file is accessible by this euid / egid by using stat() or open(). If this succeeds, you now have administrative access. 3. The following functions have write operations with potential race conditions or improper permissions: MetaOpenForWrite() Aps_AddModelFromPPD() PPDCreateCustomPPD() 4. APS should perform comprehensive authentication of access only in the high-level calls. (eg. Aps_AddPrinter, Aps_PrinterSetModel, ...) It should then ensure that the euid / egid are set to "sane" values and real uid / gid reflect the true identity of the user logged in. Low-level functions and operations involving the creation of files or manipulation of administrative settings should assume that admin files are to be created using the current euid / egid (ie. not explicitely select root to be the recipient of ownership), and use the current real uid / gid when we are interested in the user's true identity. (Like when we tag the id with a job, or store information in a log). 5. APS should not deal with passwords / switching users at all! Let the app do this as it (supposedly) knows best what is needed for each situation. To simplify things for the app, we may offer a global service for setting default admin uid / gid for functions which require it. We would then ensure that euid / egid are set to these values and restored appropriately for each administrative function unless one or both of the values in the uid/gid pair are -1. void Aps_SetDefaultAdmin( uid_t uid, gid_t gid); Aps_SetDefaultAdmin( 0, 0); /* selects root */ Aps_SetDefaultAdmin( -1, -1); /* selects "nobody", disables */ Aps_SetDefaultAdmin( -1, group); /* don't touch user */ I think this would greatly simplify the creation of administrative programs like kcmprint. It would also be possible to have APS store a "GLOBAL DEFAULT" in privileged configuration files or to request them from a secure server. Ideas??? RFC. Jeff Brown. (x5625) |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:40
|
From: "Brian Pirie" <br...@co...> Subject: Accounting and logging Date: Friday, February 04, 2000 3:40 pm One of the recommendations that I've received regarding APS is that we should have something in the way of accounting and error logging facilities, perhaps using syslogd. syslogd provides some significant facilities for configuring the type and severity of information that is logged, and so the main thing that we'd have to do is actually send log information to syslogd. Here are a couple things that immediately come to mind, as far as the type of things we might want to log: * Major failures * A job being dispatched, canceled or printed. Do you guys have any further ideas regarding this? Brian |
From: Jeff B. <kl...@ma...> - 2000-04-28 21:02:38
|
From: "Jeff Brown" <jef...@co...> Subject: C++ Wrapper ostream support Date: Friday, March 17, 2000 2:40 pm Here's a thought... What if we provided a C++ class in our wrapper derived from ostream to simplify the creation of jobs. This would effectively provide a more portable implementation of the ability we have now for constructing jobs using a file descriptor. There are many benefits to such a scheme, namely: - we can recycle all of ostream's formatting/conversion methods - more C++-like access to jobs - more intuitive file access for those who know little of the Unix filesystem primitives - improved code clarity For instance: [pseudo-code] ApsJob *job = new ApsJob(printer); ApsOStream *out = new ApsOStream(job); (*out)<<"Hello world!!!" (*out)<<123<<someVar; // may be required: (*out).flush(); delete out; Hmm... not sure if I got that right. I don't use STL much. Jeff. |
From: Brian P. <br...@co...> - 2000-04-27 16:17:46
|
Jeff, I think this is a reasonable and straightforward way to implement this API. While it does mean a little extra complexity for the application programmer to specify the mask of status fields they are interested in, I can see how, in some situations, it could allow the underlying implementation to be much more efficient if it knows exactly what information is being queried for. I do find the overloading of this parameter to return which fields were available a little awkward, but I think this is the best way of implementing it. Brian (P.S. Jeff's original message wasn't sent to the mailing list, but is quoted below.) Jeffrey Brown wrote: > Hello everyone, > > One of the tasks on my list is printer status monitoring. For this purpose > I have conjured up the following interface based on support which is already > present within APS. While I see a need to supply an operation providing > greater detail than is available here, I believe that the proposed function > will still be useful as a "distilled" status interface. As support exists > in this format, implementation will be fairly easy. Nevertheless, it may be > worthwhile to delay the introduction of this interface and to discuss > potential (better) alternatives. > > N.B. A better interface might consist of an array of structures containing > internal status classes, codes and auxiliary information. The user could > then iterate through the array and feed items of interest to a function > designed to return localized string representations of the status data. > > Jeff. > > > > > > > 3.9.2.7 Aps_PrinterGetStatus() > > Queries an open printer for a distilled set of status flags. > Aps_PrinterStatus is a bitmapped enumeration representing elemental > status qualities of printers. As not all status flags are available > for all printers, this function optionally accepts and returns the set > of flags of interest. This should only be used for presentation > purposes as not all fields are valid / available upon return from this > command. > > Aps_Result Aps_PrinterGetStatus( > Aps_PrinterHandle handle, > Aps_PrinterStatus *fieldMask > Aps_PrinterStatus *status); > > Input > > handle Handle of the printer whose status is to be queried. fieldMask Pointer to an Aps_PrinterStatus bitmapped enum which contains a list of fields that are of particular interest, or NULL for all. > > Output > > fieldMask Unless NULL, the target Aps_PrinterStatus bitmapped enum will be filled in with the set of status flags which were actually available (i.e. known good fields). status Pointer to an Aps_PrinterStatus bitmapped enum which will contain the results of the query. > > Remarks > > This function is guaranteed to return only the set of flags which the > user originally specified. > > It is not yet possible to distinguish between different forms of > printer errors or to obtain more detailed information about printer > activities. New API functions will be provided when that support > becomes available. > > Defined Fields > > Aps_PrinterStatus Bit Meaning APS_PRINTER_UNKNOWN Unknown / default status (equals zero -- no flags set) APS_PRINTER_ERROR The printer stopped on an error. APS_PRINTER_READY The printer is ready for work (online). APS_PRINTER_SUSPENDED New jobs added to the queue will not be immediately printed because the queue has been suspended. APS_PRINTER_IDLE Printer is available but is not doing anything. APS_PRINTER_ACTIVE Printer is busy doing something related to a request we made. APS_PRINTER_OCCUPIED Printer is busy doing something which is not related to a request we made. (e.g. warming up, self-cleaning, etc...) APS_PRINTER_DENY_NEW_JOBS Printer's host queue denies new jobs. (see APS_IS_QAUTODENYNEWJOBS) APS_PRINTER_PAUSE_NEW_JOBS Printer's host queue pauses new jobs. (see APS_IS_QAUTOPAUSENEWJOBS) APS_PRINTER_DISCARD_NEW_JOBS Printer's host queue discards new jobs. (see APS_IS_QAUTODISCARDNEWJOBS) APS_PRINTER_MASK_ALL Mask representing ALL status flags Special-purpose bits (avoid unless you really need them) APS_PRINTER_PAR_BUSY Parallel port BUSY line set (can't send data). (this hardware resource may not be available for many printers and may not always have the same meaning) APS_PRINTER_PAR_PAPER_OUT Parallel port PAPER OUT line set. (this hardware resource may not be available for many printers and may not always have the same meaning) APS_PRINTER_PAR_SELECT Parallel port SELECT line set. (this hardware resource may not be available for many printers and may not always have the same meaning) APS_PRINTER_PAR_ERROR Parallel port ERROR line set. (this hardware resource may not be available for many printers and may not always have the same meaning) > ----------------------------------------------------------------------- > > > > -- Brian Pirie Project Leader - Printing Technologies Corel Corporation br...@co... (613) 728-8200 x1407 |
From: Brian P. <br...@co...> - 2000-04-25 19:53:16
|
FYI, I'm still following up on why the archives and online viewing / posting mechanism is not yet working for this list. I'll post an update once the web-based list services are available. In the meantime, feel free to continue using this list via email (keeping in mind that anything you say won't be archived. ;-) Brian |
From: Brian P. <br...@co...> - 2000-04-24 17:23:36
|
Hi everyone, I've restructured the APS ToDo list into categories so that it will be easier to read. The newest version is located at: http://libaps.sourceforge.net/libaps/doc/todo.html. Regards, Brian |
From: Brian P. <br...@co...> - 2000-04-23 00:38:44
|
I want to bring everyone's attention to our current to-do list for the = Application Print Services Library. a.. Provide a common print dialog box for QT-based applications=20 b.. Creating user-level programs to access APS functionality=20 c.. Support interrogating Samba for contents of remote Windows = printer queues=20 d.. Support for determining printer type via IEEE 1284=20 e.. Restructuring transport architecture for clearer delination = between transports and the rest of the APS library, and to allow = external transports to be added without recompiling the core library.=20 f.. Length of the directory path is hardcoded to 1024; find a = generalized solution.=20 g.. Change the spool directory name to printer name, when printer is = renamed.=20 h.. Decide about the name of the directory if one exist with the = printer name.=20 i.. The .ppd file should be deleted from /etc/printers directory = when printer is removed.=20 j.. Change the APS_RESULT implementation to include information on = where an error orginated from.=20 k.. Provide return codes for job operations (ie. parse lprm output = et. al)=20 l.. Update docs for Get/SetConnectInfo=20 m.. Provide summary compatibility list for operations on various = transports=20 n.. Improve introduction of APS internal structures and objects: ie. = describe transports, printers, jobs, queues, attributes, etc...=20 o.. Implement safe writing for all configs (ie. expose explicit = Begin, Write, Read, and Abort operations for all file operations (and = perhaps other in-code structural artifacts)=20 p.. implement printer name aliases at the APS library level=20 q.. maintain high-level APS database of open printers=20 r.. improve use of Printer object as a repository for printer = config-related data=20 a.. printer config data, if referenced, should persist even if = its on-disk representations have been wiped=20 b.. Consdier keeping lists of available Printers rather than = arrays of available printer configurations (ie. Aps_Printcap_Info) = (explicit locking of resources will prevent a printer and all configs = from vanishing until all references are gone)=20 c.. need to ensure that only one instance of each printer exists = (perhaps we should pre-allocate these instances upon reading of configs = so APS high-level need only do an AddRef() before returning to user)=20 d.. Transport object holds a list of configured printers and a = list of removed/vanished printers with outstanding references (in case = they reappear) (assumption: only configured printers will appear in = printcap but instances of PrintcapInfo can persist for any still-open = printers)=20 s.. formalize design of object vector-tables=20 a.. also cleans up global name space since the related functions = can be declared static/local to the module in which the vector table is = def'd.=20 t.. provide low-overhead name-resolution and name-comparison for = printers (ie. get Printer object by name)=20 u.. provide explicit library initialization / uninitialization calls = for diagnostic purposes (locate unfreed resources, etc...)=20 v.. extend compile-time configuration options to include things like = compilation for libefence, libdmalloc, function inlining, system = capabilities, workarounds / kludges, compiling out support for specific = transports/subtransports=20 w.. simplification of transport interface=20 x.. dynamic loading / releasing of transport modules=20 a.. improved high-level interface abstraction hide communication = method from high-level calls (ie. Aps_ functions are no more than stubs = for internal functions)=20 b.. may ease transition to a daemon-oriented setup, or provide = opportunities for serializing access to various resources (ie. by = replacing high-level layer we could support daemon RPC's or wrap = function calls in a Mutex)=20 c.. may help to simplify the layout of APS and demystify the = location of various bits of functionality=20 y.. provide auto-documentation for internal APS components=20 a.. requires scanning through the list of function headers and = extracting fields like: function prototype, high-level description, = input/output parameter descriptions, return codes (error values), notes = for the user, implementation notes, known problems.=20 b.. could automatically build an HTML document indexed by = function name, by source file name, by module name, by grouping.=20 c.. we'd have to update all of our headers; this might be a good thing in the long run.=20 z.. increase available queue/job/printer/model functionality so that = individual fields may be accessed via some common means... eg. = Aps_ObjGetString(object, id, & string); Aps_ObjGetInt(object, id, & = num);=20 a.. part of this functionality already exists in the form of = object properties, but we need to formalize the documentation for it and = provide support for "active" access/modification of fields (via callback = / vtbl entry), protection of fields=20 b.. this kind of thing could help reduce the number of = Aps_<obj>Get<something> and Aps_<obj>Set<something> entry points and = also centralize most of the parameter validation procedures=20 |
From: Brian P. <br...@co...> - 2000-04-22 01:40:24
|
Welcome to this list. This list has been setup for any discussion related to the Application Print Services project. We invite your questions, ideas, suggestions, comments and bug reports. Brian Pirie Project Leader - Linux Printing Corel Corp. |